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: 0 additions & 14 deletions Lib/json/decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,6 @@ class JSONDecodeError(ValueError):
colno: The column corresponding to pos

"""
# RUSTPYTHON SPECIFIC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we probably need to keep this change

@classmethod
def _from_serde(cls, msg, doc, line, col):
pos = 0
# 0-indexed
line -= 1
col -= 1
while line > 0:
i = doc.index('\n', pos)
line -= 1
pos = i
pos += col
return cls(msg, doc, pos)

# Note that this exception is used from _json
def __init__(self, msg, doc, pos):
lineno = doc.count('\n', 0, pos) + 1
Expand Down
6 changes: 2 additions & 4 deletions Lib/test/test_json/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@


# import json with and without accelerations
# XXX RUSTPYTHON: we don't import _json as fresh since the fresh module isn't placed
# into the sys.modules cache, and therefore the vm can't recognize the _json.Scanner class
cjson = import_helper.import_fresh_module('json') #, fresh=['_json'])
cjson = import_helper.import_fresh_module('json', fresh=['_json'])
pyjson = import_helper.import_fresh_module('json', blocked=['_json'])
# JSONDecodeError is cached inside the _json module
cjson.JSONDecodeError = cjson.decoder.JSONDecodeError = json.JSONDecodeError
Expand Down Expand Up @@ -41,7 +39,7 @@ def test_pyjson(self):
'json.encoder')

class TestCTest(CTest):
@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; AttributeError: 'NoneType' object has no attribute '__module__'. Did you mean: '__reduce__'?
def test_cjson(self):
self.assertEqual(self.json.scanner.make_scanner.__module__, '_json')
self.assertEqual(self.json.decoder.scanstring.__module__, '_json')
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_json/test_decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ def test_limit_int(self):

class TestPyDecode(TestDecode, PyTest): pass
class TestCDecode(TestDecode, CTest):

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_limit_int(self):
return super().test_limit_int()
2 changes: 1 addition & 1 deletion Lib/test/test_json/test_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def test_default(self):
self.dumps(type, default=repr),
self.dumps(repr(type)))

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; 'when serializing type object']
def test_bad_default(self):
def default(obj):
if obj is NotImplemented:
Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_json/test_fail.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ def test_linecol(self):

class TestPyFail(TestFail, PyTest): pass
class TestCFail(TestFail, CTest):

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_failures(self):
return super().test_failures()
2 changes: 1 addition & 1 deletion Lib/test/test_json/test_scanstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def test_bad_escapes(self):
with self.assertRaises(self.JSONDecodeError, msg=s):
scanstring(s, 1, True)

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; json.decoder.JSONDecodeError: Unterminated string starting at: line 1 column 9223372036854775808 (char 9223372036854775807)
def test_overflow(self):
with self.assertRaises(OverflowError):
self.json.decoder.scanstring("xxx", sys.maxsize+1)
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_json/test_speedups.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def bad_encoder2(*args):
with self.assertRaises(ZeroDivisionError):
enc('spam', 4)

@unittest.expectedFailure # TODO: RUSTPYTHON
@unittest.expectedFailure # TODO: RUSTPYTHON; AssertionError: "make_encoder\(\) argument 1 must be dict or None, not int" does not match "'NoneType' object is not callable"
def test_bad_markers_argument_to_encoder(self):
# https://bugs.python.org/issue45269
with self.assertRaisesRegex(
Expand Down
7 changes: 4 additions & 3 deletions Lib/test/test_json/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,6 @@ def test_object_pairs_hook_with_unicode(self):

class TestPyUnicode(TestUnicode, PyTest): pass
class TestCUnicode(TestUnicode, CTest):
@unittest.expectedFailure # TODO: RUSTPYTHON
def test_ascii_non_printable_encode(self):
return super().test_ascii_non_printable_encode()

@unittest.skip("TODO: RUSTPYTHON; panics with 'str has surrogates'")
def test_single_surrogate_decode(self):
Expand All @@ -149,3 +146,7 @@ def test_single_surrogate_decode(self):
@unittest.skip("TODO: RUSTPYTHON; panics with 'str has surrogates'")
def test_single_surrogate_encode(self):
return super().test_single_surrogate_encode()

@unittest.expectedFailure # TODO: RUSTPYTHON; ? ^
def test_ascii_non_printable_encode(self):
return super().test_ascii_non_printable_encode()
25 changes: 24 additions & 1 deletion scripts/update_lib/cmd_auto_mark.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,30 @@ def strip_reasonless_expected_failures(
for idx in sorted(lines_to_remove, reverse=True):
del lines[idx]

return "\n".join(lines) + "\n" if lines else "", stripped_tests
# Check if any classes are now empty and add 'pass' if needed
result = "\n".join(lines) + "\n" if lines else ""
try:
result_tree = ast.parse(result)
# Track classes that need 'pass' added
classes_needing_pass = []
for node in result_tree.body:
if isinstance(node, ast.ClassDef) and len(node.body) == 0:
# Empty class - need to add pass
classes_needing_pass.append((node.lineno, node.col_offset))

if classes_needing_pass:
result_lines = result.splitlines()
# Insert 'pass' for each empty class (in reverse order to preserve line numbers)
for lineno, col_offset in reversed(classes_needing_pass):
class_line_idx = lineno - 1
indent = " " * (col_offset + 4) # Class body indent
result_lines.insert(class_line_idx + 1, f"{indent}pass")
result = "\n".join(result_lines) + "\n"
except SyntaxError:
# If result has syntax errors, return original contents
return contents, set()

return result, stripped_tests


def extract_test_methods(contents: str) -> set[tuple[str, str]]:
Expand Down
14 changes: 14 additions & 0 deletions scripts/update_lib/patch_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,20 @@ def apply_patches(contents: str, patches: Patches) -> str:
tree = ast.parse(contents)
lines = contents.splitlines()

# First pass: Expand classes with only 'pass' on the same line if they need methods added
classes_needing_methods = set(patches.keys())
for node in tree.body:
if isinstance(node, ast.ClassDef) and node.name in classes_needing_methods:
# Check if class has only 'pass' on the same line
if (
len(node.body) == 1
and isinstance(node.body[0], ast.Pass)
and node.lineno == node.end_lineno
):
# Expand the class: replace ': pass' with ':'
line_idx = node.lineno - 1 # Convert to 0-indexed
lines[line_idx] = lines[line_idx].replace(': pass', ':')

modifications = list(_iter_patch_lines(tree, patches))

# If we have modifications and unittest is not imported, add it
Expand Down
Loading