Merge pull request #1563 from yanganto/byte.mod

bytes.mod implement with CFormat
This commit is contained in:
Noah
2019-11-18 08:49:14 -06:00
committed by GitHub
5 changed files with 57 additions and 3 deletions

View File

@@ -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'

View File

@@ -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(),

View File

@@ -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,
}
}

View File

@@ -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.

View File

@@ -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(