Skip to content

Commit 124dbfb

Browse files
Merge pull request RustPython#1618 from RustPython/coolreader18/misc-changes
Some miscellaneous changes (print fix, bytes/bytearray fixes, mappingproxy iter)
2 parents 10997ae + a07e0a1 commit 124dbfb

20 files changed

+378
-100
lines changed

Lib/_sre.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@ def match(self, string, pos=0, endpos=sys.maxsize):
7070
else:
7171
return None
7272

73+
def fullmatch(self, string):
74+
"""If the whole string matches the regular expression pattern, return a
75+
corresponding match object. Return None if the string does not match the
76+
pattern; note that this is different from a zero-length match."""
77+
match = self.match(string)
78+
if match and match.start() == 0 and match.end() == len(string):
79+
return match
80+
else:
81+
return None
82+
7383
def search(self, string, pos=0, endpos=sys.maxsize):
7484
"""Scan through string looking for a location where this regular
7585
expression produces a match, and return a corresponding MatchObject
@@ -123,7 +133,7 @@ def _subx(self, template, string, count=0, subn=False):
123133
last_pos == state.string_position and n > 0):
124134
# the above ignores empty matches on latest position
125135
if callable(filter):
126-
sublist.append(list(filter(SRE_Match(self, state))))
136+
sublist.extend(filter(SRE_Match(self, state)))
127137
else:
128138
sublist.append(filter)
129139
last_pos = state.string_position
@@ -334,6 +344,8 @@ def __deepcopy__():
334344
class _State(object):
335345

336346
def __init__(self, string, start, end, flags):
347+
if isinstance(string, bytes):
348+
string = string.decode()
337349
self.string = string
338350
if start < 0:
339351
start = 0

src/main.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ fn get_paths(env_variable_name: &str) -> Vec<String> {
279279

280280
#[cfg(feature = "flame-it")]
281281
fn write_profile(matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
282-
use std::fs::File;
282+
use std::{fs, io};
283283

284284
enum ProfileFormat {
285285
Html,
@@ -306,12 +306,14 @@ fn write_profile(matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>>
306306
ProfileFormat::Speedscope => "flamescope.json".as_ref(),
307307
});
308308

309-
let profile_output: Box<dyn std::io::Write> = if profile_output == "-" {
310-
Box::new(std::io::stdout())
309+
let profile_output: Box<dyn io::Write> = if profile_output == "-" {
310+
Box::new(io::stdout())
311311
} else {
312-
Box::new(File::create(profile_output)?)
312+
Box::new(fs::File::create(profile_output)?)
313313
};
314314

315+
let profile_output = io::BufWriter::new(profile_output);
316+
315317
match profile_format {
316318
ProfileFormat::Html => flame::dump_html(profile_output)?,
317319
ProfileFormat::Text => flame::dump_text_to_writer(profile_output)?,

tests/snippets/bytearray.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@
271271
) == bytearray(b"jiljlkmoomkaaaa")
272272
with assert_raises(TypeError):
273273
bytearray(b"").join((b"km", "kl"))
274+
assert bytearray(b"abc").join((
275+
bytearray(b"123"), bytearray(b"xyz")
276+
)) == bytearray(b"123abcxyz")
274277

275278

276279
# endswith startswith

tests/snippets/bytes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@
270270
with assert_raises(TypeError):
271271
b"".join((b"km", "kl"))
272272

273+
assert b"abc".join((b"123", b"xyz")) == b"123abcxyz"
274+
273275

274276
# endswith startswith
275277
assert b"abcde".endswith(b"de")
@@ -612,3 +614,9 @@
612614
# mod
613615
assert b'rust%bpython%b' % (b' ', b'!') == b'rust python!'
614616
assert b'x=%i y=%f' % (1, 2.5) == b'x=1 y=2.500000'
617+
618+
class A:
619+
def __bytes__(self):
620+
return b"bytess"
621+
622+
assert bytes(A()) == b"bytess"

tests/snippets/generators.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,13 @@ def wrapper(coro):
131131
wrap.send(i)
132132

133133
assert l == ['>> 0', '>> 1', '>> 2', '***', '>> 4']
134+
135+
def a():
136+
yield
137+
138+
g = a()
139+
140+
next(g)
141+
assert_raises(TypeError, g.throw, TypeError)
142+
assert_raises(StopIteration, next, g)
143+
assert_raises(TypeError, g.throw, TypeError)

tests/snippets/isinstance.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,5 @@ class ReturnInt(metaclass=MCReturnInt):
5252

5353

5454
assert isinstance("a", ReturnInt) is True
55+
56+
assert isinstance(1, ((int, float,), str))

vm/src/builtins.rs

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ use crate::obj::objstr::{PyString, PyStringRef};
2525
use crate::obj::objtype::{self, PyClassRef};
2626
use crate::pyhash;
2727
use crate::pyobject::{
28-
Either, IdProtocol, IntoPyObject, ItemProtocol, PyIterable, PyObjectRef, PyResult, PyValue,
29-
TryFromObject, TypeProtocol,
28+
Either, IdProtocol, ItemProtocol, PyIterable, PyObjectRef, PyResult, PyValue, TryFromObject,
29+
TypeProtocol,
3030
};
3131
use crate::scope::Scope;
3232
use crate::stdlib::ast;
@@ -598,13 +598,13 @@ pub struct PrintOptions {
598598
}
599599

600600
trait Printer {
601-
fn write(&mut self, vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<()>;
601+
fn write(&mut self, vm: &VirtualMachine, obj: PyStringRef) -> PyResult<()>;
602602
fn flush(&mut self, vm: &VirtualMachine) -> PyResult<()>;
603603
}
604604

605605
impl Printer for &'_ PyObjectRef {
606-
fn write(&mut self, vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<()> {
607-
vm.call_method(self, "write", vec![obj])?;
606+
fn write(&mut self, vm: &VirtualMachine, obj: PyStringRef) -> PyResult<()> {
607+
vm.call_method(self, "write", vec![obj.into_object()])?;
608608
Ok(())
609609
}
610610

@@ -615,14 +615,13 @@ impl Printer for &'_ PyObjectRef {
615615
}
616616

617617
impl Printer for std::io::StdoutLock<'_> {
618-
fn write(&mut self, vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<()> {
619-
let s = vm.to_str(&obj)?;
620-
write!(self, "{}", s.as_str()).unwrap();
618+
fn write(&mut self, _vm: &VirtualMachine, s: PyStringRef) -> PyResult<()> {
619+
write!(self, "{}", s).unwrap();
621620
Ok(())
622621
}
623622

624623
fn flush(&mut self, _vm: &VirtualMachine) -> PyResult<()> {
625-
<Self as std::io::Write>::flush(self).unwrap();
624+
<Self as io::Write>::flush(self).unwrap();
626625
Ok(())
627626
}
628627
}
@@ -643,10 +642,7 @@ pub fn builtin_print(objects: Args, options: PrintOptions, vm: &VirtualMachine)
643642

644643
let sep = options
645644
.sep
646-
.as_ref()
647-
.map_or(" ", |sep| sep.as_str())
648-
.into_pyobject(vm)
649-
.unwrap();
645+
.unwrap_or_else(|| PyString::from(" ").into_ref(vm));
650646

651647
let mut first = true;
652648
for object in objects {
@@ -656,15 +652,12 @@ pub fn builtin_print(objects: Args, options: PrintOptions, vm: &VirtualMachine)
656652
printer.write(vm, sep.clone())?;
657653
}
658654

659-
printer.write(vm, object)?;
655+
printer.write(vm, vm.to_str(&object)?)?;
660656
}
661657

662658
let end = options
663659
.end
664-
.as_ref()
665-
.map_or("\n", |end| end.as_str())
666-
.into_pyobject(vm)
667-
.unwrap();
660+
.unwrap_or_else(|| PyString::from("\n").into_ref(vm));
668661
printer.write(vm, end)?;
669662

670663
if options.flush.to_bool() {

vm/src/exceptions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,9 @@ impl ExceptionZoo {
390390
let assertion_error = create_type("AssertionError", &type_type, &exception_type);
391391
let attribute_error = create_type("AttributeError", &type_type, &exception_type);
392392
let import_error = create_type("ImportError", &type_type, &exception_type);
393-
let index_error = create_type("IndexError", &type_type, &exception_type);
394-
let key_error = create_type("KeyError", &type_type, &exception_type);
395393
let lookup_error = create_type("LookupError", &type_type, &exception_type);
394+
let index_error = create_type("IndexError", &type_type, &lookup_error);
395+
let key_error = create_type("KeyError", &type_type, &lookup_error);
396396
let name_error = create_type("NameError", &type_type, &exception_type);
397397
let runtime_error = create_type("RuntimeError", &type_type, &exception_type);
398398
let reference_error = create_type("ReferenceError", &type_type, &exception_type);

vm/src/function.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -569,17 +569,35 @@ pub fn single_or_tuple_any<T: PyValue, F: Fn(PyRef<T>) -> PyResult<bool>>(
569569
message: fn(&PyObjectRef) -> String,
570570
vm: &VirtualMachine,
571571
) -> PyResult<bool> {
572-
match_class!(match obj {
573-
obj @ T => predicate(obj),
574-
tuple @ PyTuple => {
575-
for obj in tuple.elements.iter() {
576-
let inner_val = PyRef::<T>::try_from_object(vm, obj.clone())?;
577-
if predicate(inner_val)? {
578-
return Ok(true);
572+
// TODO: figure out some way to have recursive calls without... this
573+
use std::marker::PhantomData;
574+
struct Checker<'vm, T: PyValue, F: Fn(PyRef<T>) -> PyResult<bool>> {
575+
predicate: F,
576+
message: fn(&PyObjectRef) -> String,
577+
vm: &'vm VirtualMachine,
578+
t: PhantomData<T>,
579+
}
580+
impl<T: PyValue, F: Fn(PyRef<T>) -> PyResult<bool>> Checker<'_, T, F> {
581+
fn check(&self, obj: PyObjectRef) -> PyResult<bool> {
582+
match_class!(match obj {
583+
obj @ T => (self.predicate)(obj),
584+
tuple @ PyTuple => {
585+
for obj in tuple.elements.iter() {
586+
if self.check(obj.clone())? {
587+
return Ok(true);
588+
}
589+
}
590+
Ok(false)
579591
}
580-
}
581-
Ok(false)
592+
obj => Err(self.vm.new_type_error((self.message)(&obj))),
593+
})
582594
}
583-
obj => Err(vm.new_type_error(message(&obj))),
584-
})
595+
}
596+
let checker = Checker {
597+
predicate,
598+
message,
599+
vm,
600+
t: PhantomData,
601+
};
602+
checker.check(obj)
585603
}

vm/src/obj/objbool.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use num_traits::Zero;
33

44
use crate::function::PyFuncArgs;
55
use crate::pyobject::{
6-
IntoPyObject, PyContext, PyObjectRef, PyResult, TryFromObject, TypeProtocol,
6+
IdProtocol, IntoPyObject, PyContext, PyObjectRef, PyResult, TryFromObject, TypeProtocol,
77
};
88
use crate::vm::VirtualMachine;
99

@@ -29,6 +29,12 @@ impl TryFromObject for bool {
2929

3030
/// Convert Python bool into Rust bool.
3131
pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
32+
if obj.is(&vm.ctx.true_value) {
33+
return Ok(true);
34+
}
35+
if obj.is(&vm.ctx.false_value) {
36+
return Ok(false);
37+
}
3238
let rs_bool = match vm.get_method(obj.clone(), "__bool__") {
3339
Some(method_or_err) => {
3440
// If descriptor returns Error, propagate it further

0 commit comments

Comments
 (0)