forked from Rust-related/RustPython
Merge pull request #1563 from yanganto/byte.mod
bytes.mod implement with CFormat
This commit is contained in:
@@ -608,3 +608,7 @@ assert b'\xc2\xae\x75\x73\x74'.decode('ascii', 'ignore') == 'ust'
|
||||
assert b'\xc2\xae\x75\x73\x74'.decode('utf-8') == '®ust'
|
||||
assert b'\xc2\xae\x75\x73\x74'.decode() == '®ust'
|
||||
assert b'\xe4\xb8\xad\xe6\x96\x87\xe5\xad\x97'.decode('utf-8') == '中文字'
|
||||
|
||||
# mod
|
||||
assert b'rust%bpython%b' % (b' ', b'!') == b'rust python!'
|
||||
assert b'x=%i y=%f' % (1, 2.5) == b'x=1 y=2.500000'
|
||||
|
||||
@@ -48,6 +48,7 @@ pub enum CFormatPreconversor {
|
||||
Repr,
|
||||
Str,
|
||||
Ascii,
|
||||
Bytes,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -545,6 +546,11 @@ fn parse_format_type(text: &str) -> Result<(CFormatType, &str, char), CFormatErr
|
||||
chars.as_str(),
|
||||
next_char.unwrap(),
|
||||
)),
|
||||
Some('b') => Ok((
|
||||
CFormatType::String(CFormatPreconversor::Bytes),
|
||||
chars.as_str(),
|
||||
next_char.unwrap(),
|
||||
)),
|
||||
Some('a') => Ok((
|
||||
CFormatType::String(CFormatPreconversor::Ascii),
|
||||
chars.as_str(),
|
||||
|
||||
@@ -8,6 +8,7 @@ pub enum FormatPreconversor {
|
||||
Str,
|
||||
Repr,
|
||||
Ascii,
|
||||
Bytes,
|
||||
}
|
||||
|
||||
impl FormatPreconversor {
|
||||
@@ -16,6 +17,7 @@ impl FormatPreconversor {
|
||||
's' => Some(FormatPreconversor::Str),
|
||||
'r' => Some(FormatPreconversor::Repr),
|
||||
'a' => Some(FormatPreconversor::Ascii),
|
||||
'b' => Some(FormatPreconversor::Bytes),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,16 @@ use super::objslice::PySliceRef;
|
||||
use super::objstr::PyStringRef;
|
||||
use super::objtuple::PyTupleRef;
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::cformat::CFormatString;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::obj::objstr::do_cformat_string;
|
||||
use crate::pyhash;
|
||||
use crate::pyobject::{
|
||||
Either, IntoPyObject, PyClassImpl, PyContext, PyIterable, PyObjectRef, PyRef, PyResult,
|
||||
PyValue, TryFromObject,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// "bytes(iterable_of_ints) -> bytes\n\
|
||||
/// bytes(string, encoding[, errors]) -> bytes\n\
|
||||
@@ -436,6 +439,33 @@ impl PyBytesRef {
|
||||
self.repeat(n, vm)
|
||||
}
|
||||
|
||||
fn do_cformat(
|
||||
&self,
|
||||
vm: &VirtualMachine,
|
||||
format_string: CFormatString,
|
||||
values_obj: PyObjectRef,
|
||||
) -> PyResult {
|
||||
let final_string = do_cformat_string(vm, format_string, values_obj)?;
|
||||
Ok(vm.ctx.new_bytes(
|
||||
PyBytes::from_string(final_string.as_str(), "utf8", vm)?
|
||||
.inner
|
||||
.elements,
|
||||
))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mod__")]
|
||||
fn modulo(self, values: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let format_string_text = std::str::from_utf8(&self.inner.elements).unwrap();
|
||||
let format_string = CFormatString::from_str(format_string_text)
|
||||
.map_err(|err| vm.new_value_error(err.to_string()))?;
|
||||
self.do_cformat(vm, format_string, values.clone())
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmod__")]
|
||||
fn rmod(self, _values: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
|
||||
/// Return a string decoded from the given bytes.
|
||||
/// Default encoding is 'utf-8'.
|
||||
/// Default errors is 'strict', meaning that encoding errors raise a UnicodeError.
|
||||
|
||||
@@ -1278,6 +1278,7 @@ fn call_object_format(vm: &VirtualMachine, argument: PyObjectRef, format_spec: &
|
||||
Some(FormatPreconversor::Str) => vm.call_method(&argument, "__str__", vec![])?,
|
||||
Some(FormatPreconversor::Repr) => vm.call_method(&argument, "__repr__", vec![])?,
|
||||
Some(FormatPreconversor::Ascii) => vm.call_method(&argument, "__repr__", vec![])?,
|
||||
Some(FormatPreconversor::Bytes) => vm.call_method(&argument, "decode", vec![])?,
|
||||
None => argument,
|
||||
};
|
||||
let returned_type = vm.ctx.new_str(new_format_spec.to_string());
|
||||
@@ -1306,6 +1307,7 @@ fn do_cformat_specifier(
|
||||
CFormatPreconversor::Str => vm.call_method(&obj.clone(), "__str__", vec![])?,
|
||||
CFormatPreconversor::Repr => vm.call_method(&obj.clone(), "__repr__", vec![])?,
|
||||
CFormatPreconversor::Ascii => vm.call_method(&obj.clone(), "__repr__", vec![])?,
|
||||
CFormatPreconversor::Bytes => vm.call_method(&obj.clone(), "decode", vec![])?,
|
||||
};
|
||||
Ok(format_spec.format_string(get_value(&result)))
|
||||
}
|
||||
@@ -1398,11 +1400,11 @@ fn try_update_quantity_from_tuple(
|
||||
}
|
||||
}
|
||||
|
||||
fn do_cformat(
|
||||
pub fn do_cformat_string(
|
||||
vm: &VirtualMachine,
|
||||
mut format_string: CFormatString,
|
||||
values_obj: PyObjectRef,
|
||||
) -> PyResult {
|
||||
) -> PyResult<String> {
|
||||
let mut final_string = String::new();
|
||||
let num_specifiers = format_string
|
||||
.format_parts
|
||||
@@ -1501,7 +1503,17 @@ fn do_cformat(
|
||||
vm.new_type_error("not all arguments converted during string formatting".to_string())
|
||||
);
|
||||
}
|
||||
Ok(vm.ctx.new_str(final_string))
|
||||
Ok(final_string)
|
||||
}
|
||||
|
||||
fn do_cformat(
|
||||
vm: &VirtualMachine,
|
||||
format_string: CFormatString,
|
||||
values_obj: PyObjectRef,
|
||||
) -> PyResult {
|
||||
Ok(vm
|
||||
.ctx
|
||||
.new_str(do_cformat_string(vm, format_string, values_obj)?))
|
||||
}
|
||||
|
||||
fn perform_format(
|
||||
|
||||
Reference in New Issue
Block a user