Skip to content

Commit 7a8a015

Browse files
committedSep 4, 2024·
Readability and typing improvements.
1 parent d9c55bb commit 7a8a015

File tree

2 files changed

+53
-38
lines changed

2 files changed

+53
-38
lines changed
 

‎sjson/__init__.py

+17-9
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def _skip_characters_and_whitespace(stream: _InputStream, num_char_to_skip: int)
169169
_WHITESPACE_SET = frozenset([b' ', b'\t', b'\n', b'\r'])
170170

171171

172-
def _is_whitespace(char):
172+
def _is_whitespace(char: bytes | None):
173173
return char in _WHITESPACE_SET
174174

175175

@@ -230,11 +230,11 @@ def _skip_whitespace(stream: _InputStream):
230230
_IDENTIFIER_SET = frozenset(string.ascii_letters + string.digits + '_')
231231

232232

233-
def _is_identifier(obj):
233+
def _is_identifier(obj: bytes):
234234
return chr(obj[0]) in _IDENTIFIER_SET
235235

236236

237-
def _decode_escaped_character(char):
237+
def _decode_escaped_character(char: bytes):
238238
match char:
239239
case b'b':
240240
return b'\b'
@@ -289,6 +289,11 @@ def _decode_string(stream: _InputStream, allow_identifier=False):
289289

290290
while True:
291291
next_char = stream.peek()
292+
293+
# peek() cannot return None here as we don't allow peeking beyond the
294+
# end of the file
295+
assert next_char is not None
296+
292297
if parse_as_identifier and not _is_identifier(next_char):
293298
break
294299

@@ -547,8 +552,8 @@ def _escape_string(obj: str, quote=True) -> typing.Generator[str, None, None]:
547552
def _encode(
548553
obj: _SUPPORTED_ENCODE_TYPE,
549554
separators: tuple[str, str, str] = (', ', '\n', ' = '),
550-
indent=0,
551-
level=0,
555+
indent: str = '',
556+
level: int = 0,
552557
):
553558
match obj:
554559
case None:
@@ -581,7 +586,8 @@ def _encode_key(k: str):
581586

582587

583588
def _encode_list(
584-
obj: typing.Sequence, separators: tuple[str, str, str], indent: str, level: int
589+
obj: typing.Sequence, separators: tuple[str, str, str],
590+
indent: str, level: int
585591
):
586592
yield '['
587593
first = True
@@ -595,10 +601,12 @@ def _encode_list(
595601

596602

597603
def _encode_dict(
598-
obj: typing.Mapping, separators: tuple[str, str, str], indent: str, level: int
604+
obj: typing.Mapping, separators: tuple[str, str, str],
605+
indent: str, level: int
599606
):
600607
if level > 0:
601-
yield '{\n'
608+
yield '{'
609+
yield separators[1]
602610
first = True
603611
for key, value in obj.items():
604612
if first:
@@ -609,7 +617,7 @@ def _encode_dict(
609617
yield from _encode_key(key)
610618
yield separators[2]
611619
yield from _encode(value, separators, indent, level + 1)
612-
yield '\n'
620+
yield separators[1]
613621
yield _indent(level - 1, indent)
614622
if level > 0:
615623
yield '}'

‎sjson/test/test_sjson.py

+36-29
Original file line numberDiff line numberDiff line change
@@ -160,28 +160,33 @@ def testBugDecodeFailure1():
160160

161161
def testReportErrorOnIncompleteArray1():
162162
s = "test = [1, 2, "
163-
with pytest.raises(Exception):
163+
with pytest.raises(sjson.ParseException):
164164
sjson.loads(s)
165165

166166

167167
def testReportErrorOnIncompleteArray2():
168168
s = "test = ["
169-
with pytest.raises(Exception):
169+
with pytest.raises(sjson.ParseException):
170170
sjson.loads(s)
171171

172172

173173
def testReportOnIncompleteMap1():
174174
s = "test = "
175-
with pytest.raises(Exception):
175+
with pytest.raises(sjson.ParseException):
176176
sjson.loads(s)
177177

178178

179179
def testReportOnIncompleteMap2():
180180
s = "test "
181-
with pytest.raises(Exception):
181+
with pytest.raises(sjson.ParseException):
182182
sjson.loads(s)
183183

184184

185+
def testReportOnKeyOnly():
186+
with pytest.raises(sjson.ParseException):
187+
sjson.loads('foo')
188+
189+
185190
def testBugDecodeFailsForFloats():
186191
s = "test = 1.0"
187192
r = sjson.loads(s)
@@ -209,12 +214,12 @@ def testBugDecodeFailsOnStringWithDot():
209214

210215

211216
def testStringWithoutQuotesAsValueThrows():
212-
with pytest.raises(Exception):
217+
with pytest.raises(sjson.ParseException):
213218
sjson.loads("key = baz\n")
214219

215220

216221
def testStringWithoutClosingQuotesThrows():
217-
with pytest.raises(Exception):
222+
with pytest.raises(sjson.ParseException):
218223
sjson.loads('key = "baz\n')
219224

220225

@@ -249,23 +254,23 @@ def testStringWithEmptyRawLiteral():
249254

250255

251256
def testStringWithIncorrectlyTerminatedRawLiteral():
252-
with pytest.raises(Exception):
257+
with pytest.raises(sjson.ParseException):
253258
sjson.loads("""foo = [=[=]""")
254-
with pytest.raises(Exception):
259+
with pytest.raises(sjson.ParseException):
255260
sjson.loads("""foo = [=[]]""")
256-
with pytest.raises(Exception):
261+
with pytest.raises(sjson.ParseException):
257262
sjson.loads("""foo = [=[]=""")
258263

259264

260265
def testUndelimitedMapThrows():
261-
with pytest.raises(Exception):
266+
with pytest.raises(sjson.ParseException):
262267
sjson.loads('foo = { bar = "value", baz = { ui = "foo",')
263268

264269

265270
def testInvalidRawQuotedStringStart():
266-
with pytest.raises(Exception):
271+
with pytest.raises(sjson.ParseException):
267272
sjson.loads("foo = [=? wrong ?=]")
268-
with pytest.raises(Exception):
273+
with pytest.raises(sjson.ParseException):
269274
sjson.loads("foo = [=] wrong [=]")
270275

271276

@@ -307,7 +312,7 @@ def testCStyleCommentIsIgnored():
307312

308313

309314
def testNotClosedCStyleCommentThrows():
310-
with pytest.raises(Exception):
315+
with pytest.raises(sjson.ParseException):
311316
sjson.loads("""foo = /* bar * 23""")
312317

313318

@@ -319,7 +324,8 @@ def testCppStyleCommentIsIgnored():
319324

320325

321326
def testParseStringraySJSONExample():
322-
r = sjson.loads("""// The script that should be started when the application runs.
327+
r = sjson.loads(
328+
"""// The script that should be started when the application runs.
323329
boot_script = "boot"
324330
325331
// The port on which the console server runs.
@@ -407,32 +413,33 @@ def testIndentWithNegativeNumberDoesNotIndent():
407413

408414

409415
def testDoubleColonSeparator():
410-
assert sjson.loads("""{"smells-like" : "json"}""") == {'smells-like': 'json'}
416+
assert sjson.loads("""{"smells-like" : "json"}""") == {
417+
'smells-like': 'json'}
411418

412419

413420
def testUnknownEscapeGetsIgnored():
414-
l = sjson.loads(r'foo = "Bar\lbaz"')
415-
assert l['foo'] == r'Bar\lbaz'
421+
r = sjson.loads(r'foo = "Bar\lbaz"')
422+
assert r['foo'] == r'Bar\lbaz'
416423

417424

418425
def testPythonStyleString():
419-
l = sjson.loads('''foo = """This is
426+
r = sjson.loads('''foo = """This is
420427
multiline!"""''')
421428
assert (
422-
l['foo']
429+
r['foo']
423430
== """This is
424431
multiline!"""
425432
)
426433

427434

428435
def testQuadrupleQuotedString():
429-
l = sjson.loads('''Foo = """"Why oh why""""''')
430-
assert l['Foo'] == '"Why oh why"'
436+
r = sjson.loads('''Foo = """"Why oh why""""''')
437+
assert r['Foo'] == '"Why oh why"'
431438

432439

433440
def testQuintupleQuotedString():
434-
l = sjson.loads('''Foo = """""Why oh why"""""''')
435-
assert l['Foo'] == '""Why oh why""'
441+
r = sjson.loads('''Foo = """""Why oh why"""""''')
442+
assert r['Foo'] == '""Why oh why""'
436443

437444

438445
def testSixtupleQuotedStringIsInvalid():
@@ -441,13 +448,13 @@ def testSixtupleQuotedStringIsInvalid():
441448

442449

443450
def testPythonRawQuotedStringInsideLuaRawString():
444-
l = sjson.loads('''foo = [=[ String """ string ]=]''')
445-
assert l['foo'] == ''' String """ string '''
451+
r = sjson.loads('''foo = [=[ String """ string ]=]''')
452+
assert r['foo'] == ''' String """ string '''
446453

447454

448455
def testLuaRawQuotedStringInsidePythonRawString():
449-
l = sjson.loads('''foo = """ String [=[ baz ]=] string """''')
450-
assert l['foo'] == ''' String [=[ baz ]=] string '''
456+
r = sjson.loads('''foo = """ String [=[ baz ]=] string """''')
457+
assert r['foo'] == ''' String [=[ baz ]=] string '''
451458

452459

453460
def testEncodeUnknownTypeRaisesException():
@@ -459,5 +466,5 @@ class X:
459466

460467

461468
def testDecodeEscapedCharacters():
462-
l = sjson.loads('''a = "\\b\\n\\t"''')
463-
assert l['a'] == """\b\n\t"""
469+
r = sjson.loads('''a = "\\b\\n\\t"''')
470+
assert r['a'] == """\b\n\t"""

0 commit comments

Comments
 (0)
Please sign in to comment.