Skip to content

Commit ba6bb71

Browse files
authored
Merge pull request #71 from RustPython/master
Sync Fork from Upstream
2 parents d8c720c + 6b6a667 commit ba6bb71

File tree

12 files changed

+91
-56
lines changed

12 files changed

+91
-56
lines changed

Lib/pprint.py

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,33 +41,38 @@
4141
from io import StringIO as _StringIO
4242

4343
__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr",
44-
"PrettyPrinter"]
44+
"PrettyPrinter", "pp"]
4545

4646

4747
def pprint(object, stream=None, indent=1, width=80, depth=None, *,
48-
compact=False):
48+
compact=False, sort_dicts=True):
4949
"""Pretty-print a Python object to a stream [default is sys.stdout]."""
5050
printer = PrettyPrinter(
5151
stream=stream, indent=indent, width=width, depth=depth,
52-
compact=compact)
52+
compact=compact, sort_dicts=sort_dicts)
5353
printer.pprint(object)
5454

55-
def pformat(object, indent=1, width=80, depth=None, *, compact=False):
55+
def pformat(object, indent=1, width=80, depth=None, *,
56+
compact=False, sort_dicts=True):
5657
"""Format a Python object into a pretty-printed representation."""
5758
return PrettyPrinter(indent=indent, width=width, depth=depth,
58-
compact=compact).pformat(object)
59+
compact=compact, sort_dicts=sort_dicts).pformat(object)
60+
61+
def pp(object, *args, sort_dicts=False, **kwargs):
62+
"""Pretty-print a Python object"""
63+
pprint(object, *args, sort_dicts=sort_dicts, **kwargs)
5964

6065
def saferepr(object):
6166
"""Version of repr() which can handle recursive data structures."""
62-
return _safe_repr(object, {}, None, 0)[0]
67+
return _safe_repr(object, {}, None, 0, True)[0]
6368

6469
def isreadable(object):
6570
"""Determine if saferepr(object) is readable by eval()."""
66-
return _safe_repr(object, {}, None, 0)[1]
71+
return _safe_repr(object, {}, None, 0, True)[1]
6772

6873
def isrecursive(object):
6974
"""Determine if object requires a recursive representation."""
70-
return _safe_repr(object, {}, None, 0)[2]
75+
return _safe_repr(object, {}, None, 0, True)[2]
7176

7277
class _safe_key:
7378
"""Helper function for key functions when sorting unorderable objects.
@@ -97,7 +102,7 @@ def _safe_tuple(t):
97102

98103
class PrettyPrinter:
99104
def __init__(self, indent=1, width=80, depth=None, stream=None, *,
100-
compact=False):
105+
compact=False, sort_dicts=True):
101106
"""Handle pretty printing operations onto a stream using a set of
102107
configured parameters.
103108
@@ -117,6 +122,9 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *,
117122
compact
118123
If true, several items will be combined in one line.
119124
125+
sort_dicts
126+
If true, dict keys are sorted.
127+
120128
"""
121129
indent = int(indent)
122130
width = int(width)
@@ -134,6 +142,7 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *,
134142
else:
135143
self._stream = _sys.stdout
136144
self._compact = bool(compact)
145+
self._sort_dicts = sort_dicts
137146

138147
def pprint(self, object):
139148
self._format(object, self._stream, 0, 0, {}, 0)
@@ -184,7 +193,10 @@ def _pprint_dict(self, object, stream, indent, allowance, context, level):
184193
write((self._indent_per_level - 1) * ' ')
185194
length = len(object)
186195
if length:
187-
items = sorted(object.items(), key=_safe_tuple)
196+
if self._sort_dicts:
197+
items = sorted(object.items(), key=_safe_tuple)
198+
else:
199+
items = object.items()
188200
self._format_dict_items(items, stream, indent, allowance + 1,
189201
context, level)
190202
write('}')
@@ -402,7 +414,7 @@ def format(self, object, context, maxlevels, level):
402414
and flags indicating whether the representation is 'readable'
403415
and whether the object represents a recursive construct.
404416
"""
405-
return _safe_repr(object, context, maxlevels, level)
417+
return _safe_repr(object, context, maxlevels, level, self._sort_dicts)
406418

407419
def _pprint_default_dict(self, object, stream, indent, allowance, context, level):
408420
if not len(object):
@@ -487,7 +499,7 @@ def _pprint_user_string(self, object, stream, indent, allowance, context, level)
487499

488500
# Return triple (repr_string, isreadable, isrecursive).
489501

490-
def _safe_repr(object, context, maxlevels, level):
502+
def _safe_repr(object, context, maxlevels, level, sort_dicts):
491503
typ = type(object)
492504
if typ in _builtin_scalars:
493505
return repr(object), True, False
@@ -507,11 +519,13 @@ def _safe_repr(object, context, maxlevels, level):
507519
components = []
508520
append = components.append
509521
level += 1
510-
saferepr = _safe_repr
511-
items = sorted(object.items(), key=_safe_tuple)
522+
if sort_dicts:
523+
items = sorted(object.items(), key=_safe_tuple)
524+
else:
525+
items = object.items()
512526
for k, v in items:
513-
krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
514-
vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
527+
krepr, kreadable, krecur = _safe_repr(k, context, maxlevels, level, sort_dicts)
528+
vrepr, vreadable, vrecur = _safe_repr(v, context, maxlevels, level, sort_dicts)
515529
append("%s: %s" % (krepr, vrepr))
516530
readable = readable and kreadable and vreadable
517531
if krecur or vrecur:
@@ -543,7 +557,7 @@ def _safe_repr(object, context, maxlevels, level):
543557
append = components.append
544558
level += 1
545559
for o in object:
546-
orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
560+
orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level, sort_dicts)
547561
append(orepr)
548562
if not oreadable:
549563
readable = False
@@ -568,9 +582,9 @@ def _perfcheck(object=None):
568582
if object is None:
569583
object = [("string", (1, 2), [3, 4], {5: 6, 7: 8})] * 100000
570584
p = PrettyPrinter()
571-
t1 = time.time()
572-
_safe_repr(object, {}, None, 0)
573-
t2 = time.time()
585+
t1 = time.perf_counter()
586+
_safe_repr(object, {}, None, 0, True)
587+
t2 = time.perf_counter()
574588
p.pformat(object)
575589
t3 = time.time()
576590
print("_safe_repr:", t2 - t1)

Lib/test/test_pprint.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,6 @@ def setUp(self):
7676
self.b = list(range(200))
7777
self.a[-12] = self.b
7878

79-
# TODO: RUSTPYTHON
80-
@unittest.expectedFailure
8179
def test_init(self):
8280
pp = pprint.PrettyPrinter()
8381
pp = pprint.PrettyPrinter(indent=4, width=40, depth=5,
@@ -300,8 +298,6 @@ def test_sorted_dict(self):
300298
self.assertEqual(pprint.pformat({"xy\tab\n": (3,), 5: [[]], (): {}}),
301299
r"{5: [[]], 'xy\tab\n': (3,), (): {}}")
302300

303-
# TODO: RUSTPYTHON
304-
@unittest.expectedFailure
305301
def test_sort_dict(self):
306302
d = dict.fromkeys('cba')
307303
self.assertEqual(pprint.pformat(d, sort_dicts=False), "{'c': None, 'b': None, 'a': None}")

vm/src/builtins/int.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ use crate::slots::{Comparable, Hashable, PyComparisonOp};
1919
use crate::VirtualMachine;
2020
use crate::{bytesinner::PyBytesInner, byteslike::try_bytes_like};
2121
use crate::{
22-
IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue, PyClassImpl, PyComparisonValue,
23-
PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol,
22+
try_value_from_borrowed_object, IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue,
23+
PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
24+
TryFromBorrowedObject, TypeProtocol,
2425
};
2526
use rustpython_common::hash;
2627

@@ -101,10 +102,11 @@ where
101102

102103
macro_rules! impl_try_from_object_int {
103104
($(($t:ty, $to_prim:ident),)*) => {$(
104-
impl TryFromObject for $t {
105-
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
106-
let int = PyIntRef::try_from_object(vm, obj)?;
107-
try_to_primitive(&int.value, vm)
105+
impl TryFromBorrowedObject for $t {
106+
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Self> {
107+
try_value_from_borrowed_object(vm, obj, |int: &PyInt| {
108+
try_to_primitive(int.as_bigint(), vm)
109+
})
108110
}
109111
}
110112
)*};

vm/src/builtins/make_module.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mod decl {
1313
use crate::builtins::code::PyCodeRef;
1414
use crate::builtins::dict::PyDictRef;
1515
use crate::builtins::function::{PyCellRef, PyFunctionRef};
16-
use crate::builtins::int::PyIntRef;
16+
use crate::builtins::int::{self, PyIntRef};
1717
use crate::builtins::iter::{PyCallableIterator, PySequenceIterator};
1818
use crate::builtins::list::{PyList, SortOptions};
1919
use crate::builtins::pybool::IntoPyBool;
@@ -161,7 +161,7 @@ mod decl {
161161

162162
let flags = args
163163
.flags
164-
.map_or(Ok(0), |v| i32::try_from_object(vm, v.into_object()))?;
164+
.map_or(Ok(0), |v| int::try_to_primitive(v.as_bigint(), vm))?;
165165

166166
if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() {
167167
#[cfg(not(feature = "rustpython-compiler"))]

vm/src/builtins/pybool.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use super::pystr::PyStrRef;
66
use crate::function::OptionalArg;
77
use crate::vm::VirtualMachine;
88
use crate::{
9-
IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyResult, TryFromObject,
10-
TypeProtocol,
9+
IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyResult, TryFromBorrowedObject,
10+
TryFromObject, TypeProtocol,
1111
};
1212

1313
impl IntoPyObject for bool {
@@ -16,10 +16,10 @@ impl IntoPyObject for bool {
1616
}
1717
}
1818

19-
impl TryFromObject for bool {
20-
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
19+
impl TryFromBorrowedObject for bool {
20+
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<bool> {
2121
if obj.isinstance(&vm.ctx.types.int_type) {
22-
Ok(get_value(&obj))
22+
Ok(get_value(obj))
2323
} else {
2424
Err(vm.new_type_error(format!("Expected type bool, not {}", obj.class().name)))
2525
}

vm/src/pyobject.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,28 @@ impl Default for PyContext {
406406
}
407407
}
408408

409+
pub(crate) fn try_value_from_borrowed_object<T, F, R>(
410+
vm: &VirtualMachine,
411+
obj: &PyObjectRef,
412+
f: F,
413+
) -> PyResult<R>
414+
where
415+
T: PyValue,
416+
F: Fn(&T) -> PyResult<R>,
417+
{
418+
let class = T::class(vm);
419+
let special;
420+
let py_ref = if obj.isinstance(class) {
421+
obj.downcast_ref()
422+
.ok_or_else(|| pyref_payload_error(vm, class, obj))?
423+
} else {
424+
special = T::special_retrieve(vm, obj)
425+
.unwrap_or_else(|| Err(pyref_type_error(vm, class, obj)))?;
426+
&special
427+
};
428+
f(py_ref)
429+
}
430+
409431
impl<T> TryFromObject for PyRef<T>
410432
where
411433
T: PyValue,
@@ -433,7 +455,8 @@ fn pyref_payload_error(
433455
&*obj.borrow().class().name,
434456
))
435457
}
436-
fn pyref_type_error(
458+
459+
pub(crate) fn pyref_type_error(
437460
vm: &VirtualMachine,
438461
class: &PyTypeRef,
439462
obj: impl std::borrow::Borrow<PyObjectRef>,

vm/src/stdlib/codecs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mod _codecs {
1111
use crate::exceptions::PyBaseExceptionRef;
1212
use crate::function::FuncArgs;
1313
use crate::VirtualMachine;
14-
use crate::{IdProtocol, PyObjectRef, PyResult, TryFromObject};
14+
use crate::{IdProtocol, PyObjectRef, PyResult, TryFromBorrowedObject};
1515

1616
#[pyfunction]
1717
fn register(search_function: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
@@ -156,7 +156,7 @@ mod _codecs {
156156
.ok_or_else(tuple_err)?
157157
.clone();
158158
let restart =
159-
isize::try_from_object(vm, restart.clone()).map_err(|_| tuple_err())?;
159+
isize::try_from_borrowed_object(vm, restart).map_err(|_| tuple_err())?;
160160
let restart = if restart < 0 {
161161
// will still be out of bounds if it underflows ¯\_(ツ)_/¯
162162
data.len().wrapping_sub(restart.unsigned_abs())

vm/src/stdlib/os.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::utils::Either;
3030
use crate::vm::{ReprGuard, VirtualMachine};
3131
use crate::{
3232
IntoPyObject, ItemProtocol, PyObjectRef, PyRef, PyResult, PyStructSequence, PyValue,
33-
StaticType, TryFromObject, TypeProtocol,
33+
StaticType, TryFromBorrowedObject, TryFromObject, TypeProtocol,
3434
};
3535

3636
#[cfg(unix)]
@@ -1654,7 +1654,7 @@ mod _os {
16541654

16551655
#[pyfunction]
16561656
fn truncate(path: PyObjectRef, length: Offset, vm: &VirtualMachine) -> PyResult<()> {
1657-
if let Ok(fd) = i32::try_from_object(vm, path.clone()) {
1657+
if let Ok(fd) = i32::try_from_borrowed_object(vm, &path) {
16581658
return ftruncate(fd, length, vm);
16591659
}
16601660
let path = PyPathLike::try_from_object(vm, path)?;
@@ -2867,7 +2867,7 @@ mod posix {
28672867
"Each file_actions element must be a non-empty tuple".to_owned(),
28682868
)
28692869
})?;
2870-
let id = i32::try_from_object(vm, id.clone())?;
2870+
let id = i32::try_from_borrowed_object(vm, id)?;
28712871
let id = PosixSpawnFileActionIdentifier::try_from(id).map_err(|_| {
28722872
vm.new_type_error("Unknown file_actions identifier".to_owned())
28732873
})?;

vm/src/stdlib/resource.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod resource {
55
use super::super::os;
66
use crate::exceptions::IntoPyException;
77
use crate::VirtualMachine;
8-
use crate::{IntoPyObject, PyObjectRef, PyResult, PyStructSequence, TryFromObject};
8+
use crate::{IntoPyObject, PyObjectRef, PyResult, PyStructSequence, TryFromBorrowedObject};
99
use std::{io, mem};
1010

1111
cfg_if::cfg_if! {
@@ -111,9 +111,9 @@ mod resource {
111111
}
112112

113113
struct Limits(libc::rlimit);
114-
impl TryFromObject for Limits {
115-
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
116-
let seq = vm.extract_elements::<libc::rlim_t>(&obj)?;
114+
impl TryFromBorrowedObject for Limits {
115+
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Self> {
116+
let seq = vm.extract_elements::<libc::rlim_t>(obj)?;
117117
match *seq {
118118
[cur, max] => Ok(Self(libc::rlimit {
119119
rlim_cur: cur & RLIM_INFINITY,

vm/src/stdlib/select.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::vm::VirtualMachine;
2-
use crate::{PyObjectRef, PyResult, TryFromObject};
2+
use crate::{PyObjectRef, PyResult, TryFromBorrowedObject, TryFromObject};
33
use std::{io, mem};
44

55
pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef {
@@ -72,7 +72,7 @@ struct Selectable {
7272

7373
impl TryFromObject for Selectable {
7474
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
75-
let fno = RawFd::try_from_object(vm, obj.clone()).or_else(|_| {
75+
let fno = RawFd::try_from_borrowed_object(vm, &obj).or_else(|_| {
7676
let meth = vm.get_method_or_type_error(obj.clone(), "fileno", || {
7777
"select arg must be an int or object with a fileno() method".to_owned()
7878
})?;

0 commit comments

Comments
 (0)