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: 0 additions & 3 deletions Lib/test/test_json/test_speedups.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from test.test_json import CTest
from test.support import gc_collect

import unittest # XXX: RUSTPYTHON; importing to be able to skip tests


class BadBool:
def __bool__(self):
Expand Down Expand Up @@ -84,7 +82,6 @@ def test_unsortable_keys(self):
with self.assertRaises(TypeError):
self.json.encoder.JSONEncoder(sort_keys=True).encode({'a': 1, 1: 'a'})

@unittest.expectedFailure # TODO: RUSTPYTHON; TypeError: 'NoneType' object is not callable
def test_current_indent_level(self):
enc = self.json.encoder.c_make_encoder(
markers=None,
Expand Down
72 changes: 50 additions & 22 deletions crates/stdlib/src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,34 +809,44 @@ mod _json {
markers: crate::vm::common::lock::PyMutex<HashSet<usize>>,
}

#[derive(FromArgs)]
struct EncoderArgs {
#[pyarg(any)]
markers: PyObjectRef,
#[pyarg(any)]
default: PyObjectRef,
#[pyarg(any)]
encoder: PyObjectRef,
#[pyarg(any)]
indent: PyObjectRef,
#[pyarg(any)]
key_separator: PyStrRef,
#[pyarg(any)]
item_separator: PyStrRef,
#[pyarg(any)]
sort_keys: PyObjectRef,
#[pyarg(any)]
skipkeys: PyObjectRef,
#[pyarg(any)]
allow_nan: PyObjectRef,
}

impl Constructor for JsonEncoder {
// markers, default, encoder, indent, key_separator, item_separator,
// sort_keys, skipkeys, allow_nan -- exactly as `encoder.py` calls
// `c_make_encoder`.
// Nested tuple: `FromArgs` is only implemented up to 8-tuples, and
// nested tuples count as a single top-level slot while still
// consuming their own positional arguments in order.
type Args = (
PyObjectRef,
PyObjectRef,
PyObjectRef,
PyObjectRef,
PyStrRef,
PyStrRef,
(PyObjectRef, PyObjectRef, PyObjectRef),
);
type Args = EncoderArgs;

fn py_new(
_cls: &Py<PyType>,
(
EncoderArgs {
markers,
default,
encoder,
indent,
key_separator,
item_separator,
(sort_keys, skipkeys, allow_nan),
): Self::Args,
sort_keys,
skipkeys,
allow_nan,
}: Self::Args,
vm: &VirtualMachine,
) -> PyResult<Self> {
let check_circular = if vm.is_none(&markers) {
Expand Down Expand Up @@ -1334,11 +1344,29 @@ mod _json {
}
}

impl Callable for JsonEncoder {
type Args = (PyObjectRef, PyObjectRef);
#[derive(FromArgs)]
struct EncoderCallArgs {
#[pyarg(any)]
obj: PyObjectRef,
#[pyarg(any)]
_current_indent_level: PyObjectRef,
}

fn call(zelf: &Py<Self>, (obj, indent_level): Self::Args, vm: &VirtualMachine) -> PyResult {
let level: isize = indent_level.try_index(vm)?.try_to_primitive(vm)?;
impl Callable for JsonEncoder {
type Args = EncoderCallArgs;

fn call(
zelf: &Py<Self>,
EncoderCallArgs {
obj,
_current_indent_level,
}: Self::Args,
vm: &VirtualMachine,
) -> PyResult {
let level: isize = _current_indent_level.try_index(vm)?.try_to_primitive(vm)?;
// CPython starts its indent cache with indent * initial_level;
// negative string repetition produces the same prefix as zero.
let level = level.max(0);
let mut out = Wtf8Buf::new();
zelf.encode_value(&obj, level, &mut out, vm)?;
Ok(vm.new_tuple((out,)).into())
Expand Down
Loading