JsonhPy 2.5__tar.gz → 2.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: JsonhPy
3
- Version: 2.5
3
+ Version: 2.7
4
4
  Summary: JSON for Humans in Python.
5
5
  Author-email: Joyless <joyless.mod@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "JsonhPy"
3
- version = "2.5"
3
+ version = "2.7"
4
4
  authors = [
5
5
  { name="Joyless", email="joyless.mod@gmail.com" },
6
6
  ]
@@ -1,6 +1,6 @@
1
1
  import math
2
2
  from enum import Enum
3
- from typing import Iterator, Iterable
3
+ from typing import Iterator, Iterable, cast
4
4
  import json
5
5
 
6
6
  class JsonhResult[T, E]:
@@ -8,28 +8,28 @@ class JsonhResult[T, E]:
8
8
  value_or_none: T | None
9
9
  error_or_none: E | None
10
10
 
11
- def __init__(self, is_error: bool, value_or_none: T | None = None, error_or_none: E | None = None):
11
+ def __init__(self, is_error: bool, value_or_none: T | None = None, error_or_none: E | None = None) -> None:
12
12
  self.is_error = is_error
13
13
  self.value_or_none = value_or_none
14
14
  self.error_or_none = error_or_none
15
15
 
16
16
  @staticmethod
17
- def from_value[T, E](value: T = None) -> "JsonhResult[T, E]":
18
- return JsonhResult(False, value, None)
17
+ def from_value[_T, _E](value: _T = None) -> "JsonhResult[_T, _E]": # type: ignore
18
+ return JsonhResult[_T, _E](False, value, None)
19
19
 
20
20
  @staticmethod
21
- def from_error[T, E](error: E = None) -> "JsonhResult[T, E]":
22
- return JsonhResult(True, None, error)
21
+ def from_error[_T, _E](error: _E = None) -> "JsonhResult[_T, _E]": # type: ignore
22
+ return JsonhResult[_T, _E](True, None, error)
23
23
 
24
24
  def value(self) -> T:
25
25
  if self.is_error:
26
26
  raise RuntimeError(f"Result was error: {self.error_or_none}")
27
- return self.value_or_none
27
+ return self.value_or_none # type: ignore
28
28
 
29
29
  def error(self) -> E:
30
30
  if not self.is_error:
31
31
  raise RuntimeError(f"Result was value: {self.value_or_none}")
32
- return self.error_or_none
32
+ return self.error_or_none # type: ignore
33
33
 
34
34
  def __repr__(self) -> str:
35
35
  if self.is_error:
@@ -39,7 +39,7 @@ class JsonhResult[T, E]:
39
39
  class JsonhRef[T]:
40
40
  ref: T
41
41
 
42
- def __init__(self, ref: T):
42
+ def __init__(self, ref: T) -> None:
43
43
  self.ref = ref
44
44
 
45
45
  class JsonhVersion(Enum):
@@ -135,10 +135,13 @@ class JsonTokenType(Enum):
135
135
  """
136
136
 
137
137
  class JsonhToken:
138
+ """
139
+ A single JSONH token.
140
+ """
138
141
  json_type: JsonTokenType
139
142
  value: str
140
143
 
141
- def __init__(self, json_type: JsonTokenType, value: str = ""):
144
+ def __init__(self, json_type: JsonTokenType, value: str = "") -> None:
142
145
  self.json_type = json_type
143
146
  self.value = value
144
147
 
@@ -185,7 +188,7 @@ class JsonhNumberParser:
185
188
 
186
189
  # Apply sign
187
190
  if sign != 1:
188
- number.value_or_none *= sign
191
+ number.value_or_none *= sign # type: ignore
189
192
  return number
190
193
 
191
194
  @staticmethod
@@ -306,7 +309,7 @@ class JsonhNumberParser:
306
309
  return JsonhResult.from_value(integer)
307
310
 
308
311
  @staticmethod
309
- def _index_of_any(input: str, chars: Iterable[str]) -> float:
312
+ def _index_of_any(input: str, chars: Iterable[str]) -> int:
310
313
  for i in range(0, len(input)):
311
314
  char: str = input[i]
312
315
  if char in chars:
@@ -317,7 +320,7 @@ class JsonhReaderOptions:
317
320
  """
318
321
  Options for a JsonhReader.
319
322
  """
320
- version: JsonhVersion.LATEST
323
+ version: JsonhVersion = JsonhVersion.LATEST
321
324
  """
322
325
  Specifies the major version of the JSONH specification to use.
323
326
  """
@@ -363,7 +366,7 @@ class JsonhReaderOptions:
363
366
  Only some tokens can be incomplete in this mode, so it should not be relied upon.
364
367
  """
365
368
 
366
- def __init__(self, version: JsonhVersion = JsonhVersion.LATEST, parse_single_element: bool = False, max_depth: int = 64, incomplete_inputs: bool = False):
369
+ def __init__(self, version: JsonhVersion = JsonhVersion.LATEST, parse_single_element: bool = False, max_depth: int = 64, incomplete_inputs: bool = False) -> None:
367
370
  """
368
371
  Constructs options for a JsonhReader.
369
372
  """
@@ -385,11 +388,14 @@ class JsonhReaderOptions:
385
388
  return options_version.value >= given_version.value
386
389
 
387
390
  class JsonhReader:
391
+ """
392
+ A reader that reads JSONH tokens from a `str`.
393
+ """
388
394
  string: str
389
395
  """
390
396
  The string to read characters from.
391
397
  """
392
- index: int
398
+ string_index: int
393
399
  """
394
400
  The index in the string.
395
401
  """
@@ -438,7 +444,7 @@ class JsonhReader:
438
444
  Constructs a reader that reads JSONH from a string.
439
445
  """
440
446
  self.string = string
441
- self.index = 0
447
+ self.string_index = 0
442
448
  self.options = options
443
449
  self.char_counter = 0
444
450
  self.depth = 0
@@ -466,12 +472,12 @@ class JsonhReader:
466
472
  return True
467
473
  # Array item
468
474
  if current_property_name == None:
469
- current_array: list[object] = current_elements[-1]
475
+ current_array: list[object] = cast(list[object], current_elements[-1])
470
476
  current_array.append(element)
471
477
  return False
472
478
  # Object property
473
479
  else:
474
- current_object: dict[str, object] = current_elements[-1]
480
+ current_object: dict[str, object] = cast(dict[str, object], current_elements[-1])
475
481
  current_object[current_property_name] = element
476
482
  current_property_name = None
477
483
  return False
@@ -495,40 +501,40 @@ class JsonhReader:
495
501
  match token_result.value().json_type:
496
502
  # Null
497
503
  case JsonTokenType.NULL:
498
- element: None = None
499
- if submit_element(element):
500
- return JsonhResult.from_value(element)
504
+ element_null: None = None
505
+ if submit_element(element_null):
506
+ return JsonhResult.from_value(element_null)
501
507
  # True
502
508
  case JsonTokenType.TRUE:
503
- element: bool = True
504
- if submit_element(element):
505
- return JsonhResult.from_value(element)
509
+ element_true: bool = True
510
+ if submit_element(element_true):
511
+ return JsonhResult.from_value(element_true)
506
512
  # False
507
513
  case JsonTokenType.FALSE:
508
- element: bool = False
509
- if submit_element(element):
510
- return JsonhResult.from_value(element)
514
+ element_false: bool = False
515
+ if submit_element(element_false):
516
+ return JsonhResult.from_value(element_false)
511
517
  # String
512
518
  case JsonTokenType.STRING:
513
- element: bool = token_result.value().value
514
- if submit_element(element):
515
- return JsonhResult.from_value(element)
519
+ element_string: str = token_result.value().value
520
+ if submit_element(element_string):
521
+ return JsonhResult.from_value(element_string)
516
522
  # Number
517
523
  case JsonTokenType.NUMBER:
518
- result: JsonhResult[float] = JsonhNumberParser.parse(token_result.value().value)
524
+ result: JsonhResult[float, str] = JsonhNumberParser.parse(token_result.value().value)
519
525
  if result.is_error:
520
526
  return JsonhResult.from_error(result.error())
521
- element: float = result.value()
522
- if submit_element(element):
523
- return JsonhResult.from_value(element)
527
+ element_number: float = result.value()
528
+ if submit_element(element_number):
529
+ return JsonhResult.from_value(element_number)
524
530
  # Start Object
525
531
  case JsonTokenType.START_OBJECT:
526
- element: dict[str, object] = {}
527
- start_element(element)
532
+ element_object: dict[str, object] = {}
533
+ start_element(element_object)
528
534
  # Start Array
529
535
  case JsonTokenType.START_ARRAY:
530
- element: list[object] = []
531
- start_element(element)
536
+ element_array: list[object] = []
537
+ start_element(element_array)
532
538
  # End Object/Array
533
539
  case JsonTokenType.END_OBJECT | JsonTokenType.END_ARRAY:
534
540
  # Nested element
@@ -547,6 +553,9 @@ class JsonhReader:
547
553
  case _:
548
554
  return JsonhResult.from_error("Token type not implemented")
549
555
 
556
+ # End of input
557
+ return JsonhResult.from_error("Expected token, got end of input")
558
+
550
559
  next_element: JsonhResult[object, str] = parse_next_element()
551
560
 
552
561
  # Ensure exactly one element
@@ -571,21 +580,21 @@ class JsonhReader:
571
580
 
572
581
  def parse_next_element_as_json() -> JsonhResult[str, str]:
573
582
  current_depth: int = 0
574
- isStartOfStructure: bool = True
583
+ is_start_of_structure: bool = True
575
584
  is_property_value: bool = False
576
585
 
577
586
  result_builder: str = ""
578
587
 
579
588
  for token_result in self.read_element():
580
589
  # Check error
581
- if (token_result.is_error):
590
+ if token_result.is_error:
582
591
  return JsonhResult.from_error(token_result.error())
583
592
  token: JsonhToken = token_result.value()
584
593
 
585
594
  # Add comments and indents
586
595
  if not is_property_value:
587
596
  # Add comma before property/item
588
- if (token.json_type not in [JsonTokenType.NONE, JsonTokenType.COMMENT]) and (current_depth > 0) and (not isStartOfStructure):
597
+ if (token.json_type not in [JsonTokenType.NONE, JsonTokenType.COMMENT]) and (current_depth > 0) and (not is_start_of_structure):
589
598
  # Don't add trailing comma
590
599
  if token.json_type not in [JsonTokenType.END_OBJECT, JsonTokenType.END_ARRAY]:
591
600
  result_builder += ','
@@ -593,9 +602,9 @@ class JsonhReader:
593
602
  # Apply indentation
594
603
  if indent != None:
595
604
  # Don't indent inside empty structures
596
- if not (token.json_type in [JsonTokenType.END_OBJECT, JsonTokenType.END_ARRAY] and isStartOfStructure):
605
+ if not (token.json_type in [JsonTokenType.END_OBJECT, JsonTokenType.END_ARRAY] and is_start_of_structure):
597
606
  # Don't indent comment if not included
598
- if (not (token.json_type == JsonTokenType.COMMENT and (not include_comments))):
607
+ if not (token.json_type == JsonTokenType.COMMENT and (not include_comments)):
599
608
  # Don't indent root elements
600
609
  if current_depth > 0:
601
610
  # Add newline before element
@@ -611,9 +620,9 @@ class JsonhReader:
611
620
  result_builder += indent
612
621
  # Track start of structure to avoid adding leading comma
613
622
  if token.json_type not in [JsonTokenType.NONE, JsonTokenType.COMMENT]:
614
- isStartOfStructure = False
623
+ is_start_of_structure = False
615
624
  if token.json_type in [JsonTokenType.START_OBJECT, JsonTokenType.START_ARRAY]:
616
- isStartOfStructure = True
625
+ is_start_of_structure = True
617
626
 
618
627
  match token.json_type:
619
628
  # Null
@@ -638,8 +647,8 @@ class JsonhReader:
638
647
  return JsonhResult.from_value(result_builder)
639
648
  # Number
640
649
  case JsonTokenType.NUMBER:
641
- result: JsonhResult[float] = JsonhNumberParser.parse(token_result.value().value)
642
- if (result.is_error):
650
+ result: JsonhResult[float, str] = JsonhNumberParser.parse(token_result.value().value)
651
+ if result.is_error:
643
652
  return JsonhResult.from_error(result.error())
644
653
  result_builder += str(result.value()).removesuffix(".0")
645
654
  if current_depth == 0:
@@ -672,7 +681,7 @@ class JsonhReader:
672
681
  result_builder += ' '
673
682
  # Comment
674
683
  case JsonTokenType.COMMENT:
675
- if (include_comments):
684
+ if include_comments:
676
685
  result_builder += "/*"
677
686
  result_builder += token.value.replace("/*", "/ *").replace("*/", "* /")
678
687
  result_builder += "*/"
@@ -745,7 +754,7 @@ class JsonhReader:
745
754
  # Peek char
746
755
  return self._peek() != None
747
756
 
748
- def read_end_of_elements(self) -> Iterator[JsonhResult]:
757
+ def read_end_of_elements(self) -> Iterator[JsonhResult[JsonhToken, str]]:
749
758
  """
750
759
  Reads comments and whitespace and errors if the reader contains another element.
751
760
  """
@@ -840,6 +849,7 @@ class JsonhReader:
840
849
  return
841
850
  # Missing closing brace
842
851
  yield JsonhResult.from_error("Expected `}` to end object, got end of input")
852
+ return
843
853
 
844
854
  # Closing brace
845
855
  if next == '}':
@@ -964,14 +974,12 @@ class JsonhReader:
964
974
  # Optional comma
965
975
  self._read_one(',')
966
976
 
967
- def _read_property_name(self, string: str | None = None) -> Iterator[JsonhResult[JsonhToken, str]]:
977
+ def _read_property_name(self) -> Iterator[JsonhResult[JsonhToken, str]]:
968
978
  # String
969
- if string == None:
970
- string_token: JsonhResult[JsonhToken, str] = self._read_string()
971
- if string_token.is_error:
972
- yield string_token
973
- return
974
- string = string_token.value().value
979
+ string_token: JsonhResult[JsonhToken, str] = self._read_string()
980
+ if string_token.is_error:
981
+ yield string_token
982
+ return
975
983
 
976
984
  # Comments & whitespace
977
985
  for token in self._read_comments_and_whitespace():
@@ -986,7 +994,7 @@ class JsonhReader:
986
994
  return
987
995
 
988
996
  # End of property name
989
- yield JsonhResult.from_value(JsonhToken(JsonTokenType.PROPERTY_NAME, string))
997
+ yield JsonhResult.from_value(JsonhToken(JsonTokenType.PROPERTY_NAME, string_token.value().value))
990
998
 
991
999
  def _read_array(self) -> Iterator[JsonhResult[JsonhToken, str]]:
992
1000
  # Opening bracket
@@ -1071,7 +1079,7 @@ class JsonhReader:
1071
1079
  return self._read_quoteless_string("", is_verbatim)
1072
1080
 
1073
1081
  # Count multiple quotes
1074
- start_quote_counter = 1
1082
+ start_quote_counter: int = 1
1075
1083
  while self._read_one(start_quote):
1076
1084
  start_quote_counter += 1
1077
1085
 
@@ -1086,24 +1094,24 @@ class JsonhReader:
1086
1094
  string_builder: str = ""
1087
1095
 
1088
1096
  while True:
1089
- next: str | None = self._read()
1090
- if next == None:
1097
+ next2: str | None = self._read()
1098
+ if next2 == None:
1091
1099
  return JsonhResult.from_error("Expected end of string, got end of input")
1092
1100
 
1093
1101
  # Partial end quote was actually part of string
1094
- if next != start_quote:
1102
+ if next2 != start_quote:
1095
1103
  string_builder += start_quote * end_quote_counter
1096
1104
  end_quote_counter = 0
1097
1105
 
1098
1106
  # End quote
1099
- if next == start_quote:
1107
+ if next2 == start_quote:
1100
1108
  end_quote_counter += 1
1101
1109
  if end_quote_counter == start_quote_counter:
1102
1110
  break
1103
1111
  # Escape sequence
1104
- elif next == '\\':
1112
+ elif next2 == '\\':
1105
1113
  if is_verbatim:
1106
- string_builder += next
1114
+ string_builder += next2
1107
1115
  else:
1108
1116
  escape_sequence_result: JsonhResult[str, str] = self._read_escape_sequence()
1109
1117
  if escape_sequence_result.is_error:
@@ -1111,7 +1119,7 @@ class JsonhReader:
1111
1119
  string_builder += escape_sequence_result.value()
1112
1120
  # Literal character
1113
1121
  else:
1114
- string_builder += next
1122
+ string_builder += next2
1115
1123
 
1116
1124
  # Condition: skip remaining steps unless started with multiple quotes
1117
1125
  if start_quote_counter > 1:
@@ -1120,19 +1128,19 @@ class JsonhReader:
1120
1128
  leading_whitespace_newline_counter: int = 0
1121
1129
  index: int = 0
1122
1130
  while index < len(string_builder):
1123
- next: str = string_builder[index]
1131
+ next3: str = string_builder[index]
1124
1132
 
1125
1133
  # Newline
1126
- if next in self._NEWLINE_CHARS:
1134
+ if next3 in self._NEWLINE_CHARS:
1127
1135
  # Join CR LF
1128
- if next == '\r' and index + 1 < len(string_builder) and string_builder[index + 1] == '\n':
1136
+ if next3 == '\r' and index + 1 < len(string_builder) and string_builder[index + 1] == '\n':
1129
1137
  index += 1
1130
1138
 
1131
1139
  has_leading_whitespace_newline = True
1132
1140
  leading_whitespace_newline_counter = index + 1
1133
1141
  break
1134
1142
  # Non-whitespace
1135
- elif next not in self._WHITESPACE_CHARS:
1143
+ elif next3 not in self._WHITESPACE_CHARS:
1136
1144
  break
1137
1145
 
1138
1146
  index += 1
@@ -1145,19 +1153,19 @@ class JsonhReader:
1145
1153
  trailing_whitespace_counter: int = 0
1146
1154
  index: int = 0
1147
1155
  while index < len(string_builder):
1148
- next: str = string_builder[index]
1156
+ next4: str = string_builder[index]
1149
1157
 
1150
1158
  # Newline
1151
- if next in self._NEWLINE_CHARS:
1159
+ if next4 in self._NEWLINE_CHARS:
1152
1160
  has_trailing_newline_whitespace = True
1153
1161
  last_newline_index = index
1154
1162
  trailing_whitespace_counter = 0
1155
1163
 
1156
1164
  # Join CR LF
1157
- if next == '\r' and index + 1 < len(string_builder) and string_builder[index + 1] == '\n':
1165
+ if next4 == '\r' and index + 1 < len(string_builder) and string_builder[index + 1] == '\n':
1158
1166
  index += 1
1159
1167
  # Whitespace
1160
- elif next in self._WHITESPACE_CHARS:
1168
+ elif next4 in self._WHITESPACE_CHARS:
1161
1169
  trailing_whitespace_counter += 1
1162
1170
  # Non-whitespace
1163
1171
  else:
@@ -1181,14 +1189,14 @@ class JsonhReader:
1181
1189
  line_leading_whitespace_counter: int = 0
1182
1190
  index: int = 0
1183
1191
  while index < len(string_builder):
1184
- next: str = string_builder[index]
1192
+ next5: str = string_builder[index]
1185
1193
 
1186
1194
  # Newline
1187
- if next in self._NEWLINE_CHARS:
1195
+ if next5 in self._NEWLINE_CHARS:
1188
1196
  is_line_leading_whitespace = True
1189
1197
  line_leading_whitespace_counter = 0
1190
1198
  # Whitespace
1191
- elif next in self._WHITESPACE_CHARS:
1199
+ elif next5 in self._WHITESPACE_CHARS:
1192
1200
  if is_line_leading_whitespace:
1193
1201
  # Increment line-leading whitespace
1194
1202
  line_leading_whitespace_counter += 1
@@ -1232,7 +1240,7 @@ class JsonhReader:
1232
1240
  if is_verbatim:
1233
1241
  string_builder += next
1234
1242
  else:
1235
- escape_sequence_result: JsonhResult[str] = self._read_escape_sequence()
1243
+ escape_sequence_result: JsonhResult[str, str] = self._read_escape_sequence()
1236
1244
  if escape_sequence_result.is_error:
1237
1245
  return JsonhResult.from_error(escape_sequence_result.error())
1238
1246
  string_builder += escape_sequence_result.value()
@@ -1338,9 +1346,9 @@ class JsonhReader:
1338
1346
  has_leading_zero = False
1339
1347
 
1340
1348
  # Read main number
1341
- main_result: JsonhResult[None, None] = self._read_number_no_exponent(number_builder, base_digits, has_base_specifier, has_leading_zero)
1349
+ main_result: JsonhResult[None, str] = self._read_number_no_exponent(number_builder, base_digits, has_base_specifier, has_leading_zero)
1342
1350
  if main_result.is_error:
1343
- number: JsonhResult[None, str] = JsonhResult.from_error(main_result.error())
1351
+ number: JsonhResult[JsonhToken, str] = JsonhResult.from_error(main_result.error())
1344
1352
  partial_chars_read: str = number_builder.ref
1345
1353
  return number, partial_chars_read
1346
1354
 
@@ -1353,16 +1361,16 @@ class JsonhReader:
1353
1361
 
1354
1362
  # Missing digit between base specifier and exponent (e.g. `0xe+`)
1355
1363
  if has_base_specifier and len(number_builder.ref) == 4:
1356
- number: JsonhResult[None, str] = JsonhResult.from_error("Missing digit between base specifier and exponent")
1364
+ number2: JsonhResult[JsonhToken, str] = JsonhResult.from_error("Missing digit between base specifier and exponent")
1357
1365
  partial_chars_read: str = number_builder.ref
1358
- return number, partial_chars_read
1366
+ return number2, partial_chars_read
1359
1367
 
1360
1368
  # Read exponent number
1361
- exponent_result: JsonhResult[None, None] = self._read_number_no_exponent(number_builder, base_digits)
1369
+ exponent_result: JsonhResult[None, str] = self._read_number_no_exponent(number_builder, base_digits)
1362
1370
  if exponent_result.is_error:
1363
- number: JsonhResult[None, str] = JsonhResult.from_error(exponent_result.error())
1371
+ number3: JsonhResult[JsonhToken, str] = JsonhResult.from_error(exponent_result.error())
1364
1372
  partial_chars_read: str = number_builder.ref
1365
- return number, partial_chars_read
1373
+ return number3, partial_chars_read
1366
1374
  # Exponent
1367
1375
  else:
1368
1376
  exponent_char: str | None = self._read_any('e', 'E')
@@ -1375,20 +1383,20 @@ class JsonhReader:
1375
1383
  number_builder.ref += exponent_sign
1376
1384
 
1377
1385
  # Read exponent number
1378
- exponent_result: JsonhResult[None, None] = self._read_number_no_exponent(number_builder, base_digits)
1379
- if exponent_result.is_error:
1380
- number: JsonhResult[None, str] = JsonhResult.from_error(exponent_result.error())
1386
+ exponent_result2: JsonhResult[None, str] = self._read_number_no_exponent(number_builder, base_digits)
1387
+ if exponent_result2.is_error:
1388
+ number4: JsonhResult[JsonhToken, str] = JsonhResult.from_error(exponent_result2.error())
1381
1389
  partial_chars_read: str = number_builder.ref
1382
- return number, partial_chars_read
1390
+ return number4, partial_chars_read
1383
1391
 
1384
1392
  # End of number
1385
- number: JsonhResult[JsonhToken, str] = JsonhResult.from_value(JsonhToken(JsonTokenType.NUMBER, number_builder.ref))
1393
+ number5: JsonhResult[JsonhToken, str] = JsonhResult.from_value(JsonhToken(JsonTokenType.NUMBER, number_builder.ref))
1386
1394
  partial_chars_read: str = ""
1387
- return number, partial_chars_read
1395
+ return number5, partial_chars_read
1388
1396
 
1389
- def _read_number_no_exponent(self, number_builder: JsonhRef[str], base_digits: str, has_base_specifier: bool = False, has_leading_zero: bool = False) -> JsonhResult[None, None]:
1397
+ def _read_number_no_exponent(self, number_builder: JsonhRef[str], base_digits: str, has_base_specifier: bool = False, has_leading_zero: bool = False) -> JsonhResult[None, str]:
1390
1398
  # Leading underscore
1391
- if (not has_base_specifier) and not (has_leading_zero) and self._peek() == '_':
1399
+ if (not has_base_specifier) and (not has_leading_zero) and self._peek() == '_':
1392
1400
  return JsonhResult.from_error("Leading `_` in number")
1393
1401
 
1394
1402
  is_fraction: bool = False
@@ -1660,7 +1668,7 @@ class JsonhReader:
1660
1668
  case 'U':
1661
1669
  return self._read_hex_escape_sequence(8, high_surrogate)
1662
1670
  # Escaped newline
1663
- case self._NEWLINE_CHARS:
1671
+ case _ if escape_char in self._NEWLINE_CHARS:
1664
1672
  # Join CR LF
1665
1673
  if escape_char == 'r':
1666
1674
  self._read_one('\n')
@@ -1707,16 +1715,16 @@ class JsonhReader:
1707
1715
  return code_point >= 0xDC00 and code_point <= 0xDFFF
1708
1716
 
1709
1717
  def _peek(self) -> str | None:
1710
- if self.index >= len(self.string):
1718
+ if self.string_index >= len(self.string):
1711
1719
  return None
1712
- next: str = self.string[self.index]
1720
+ next: str = self.string[self.string_index]
1713
1721
  return next
1714
1722
 
1715
1723
  def _read(self) -> str | None:
1716
- if self.index >= len(self.string):
1724
+ if self.string_index >= len(self.string):
1717
1725
  return None
1718
- next: str = self.string[self.index]
1719
- self.index += 1
1726
+ next: str = self.string[self.string_index]
1727
+ self.string_index += 1
1720
1728
  self.char_counter += 1
1721
1729
  return next
1722
1730
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: JsonhPy
3
- Version: 2.5
3
+ Version: 2.7
4
4
  Summary: JSON for Humans in Python.
5
5
  Author-email: Joyless <joyless.mod@gmail.com>
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes
File without changes