Skip to content

Commit 374a956

Browse files
committed
Misc changes; exception chaining, PyBytesLike::into_buffer
1 parent 4db7a23 commit 374a956

4 files changed

Lines changed: 70 additions & 23 deletions

File tree

vm/src/byteslike.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ impl PyRwBytesLike {
4747
}
4848
}
4949

50+
impl PyBytesLike {
51+
pub fn into_buffer(self) -> BufferRef {
52+
self.0
53+
}
54+
}
55+
5056
impl TryFromObject for PyBytesLike {
5157
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
5258
let buffer = try_buffer_from_object(vm, &obj)?;
@@ -88,8 +94,8 @@ pub fn try_rw_bytes_like<R>(
8894
.ok_or_else(|| vm.new_type_error("buffer is not a read-write bytes-like object".to_owned()))
8995
}
9096

91-
impl TryFromObject for PyRwBytesLike {
92-
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
97+
impl PyRwBytesLike {
98+
pub fn new(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Self> {
9399
let buffer = try_buffer_from_object(vm, &obj)?;
94100
if !buffer.get_options().contiguous {
95101
Err(vm.new_type_error("non-contiguous buffer is not a bytes-like object".to_owned()))
@@ -99,6 +105,16 @@ impl TryFromObject for PyRwBytesLike {
99105
Ok(Self(buffer))
100106
}
101107
}
108+
109+
pub fn into_buffer(self) -> BufferRef {
110+
self.0
111+
}
112+
}
113+
114+
impl TryFromObject for PyRwBytesLike {
115+
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
116+
Self::new(vm, &obj)
117+
}
102118
}
103119

104120
impl<'a> BorrowValue<'a> for PyRwBytesLike {

vm/src/exceptions.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,17 @@ impl PyBaseException {
152152
}
153153
}
154154

155+
pub fn chain<T>(e1: PyResult<()>, e2: PyResult<T>) -> PyResult<T> {
156+
match (e1, e2) {
157+
(Err(e1), Err(e)) => {
158+
e.set_context(Some(e1));
159+
Err(e)
160+
}
161+
(Err(e), Ok(_)) | (Ok(()), Err(e)) => Err(e),
162+
(Ok(()), Ok(close_res)) => Ok(close_res),
163+
}
164+
}
165+
155166
/// Print exception chain by calling sys.excepthook
156167
pub fn print_exception(vm: &VirtualMachine, exc: PyBaseExceptionRef) {
157168
let write_fallback = |exc, errstr| {

vm/src/frame.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,15 @@ impl ExecutingFrame<'_> {
865865
return Ok(None);
866866
}
867867
}
868-
BlockType::FinallyHandler { .. } => {
868+
BlockType::FinallyHandler {
869+
reason: finally_reason,
870+
} => {
871+
if let Some(UnwindReason::Raising { exception }) = finally_reason {
872+
let finally_exc = exception;
873+
if let UnwindReason::Raising { exception } = &reason {
874+
exception.set_context(Some(finally_exc))
875+
}
876+
}
869877
self.pop_block();
870878
}
871879
BlockType::ExceptHandler => {

vm/src/function.rs

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -187,25 +187,8 @@ impl FuncArgs {
187187
/// during the conversion will halt the binding and return the error.
188188
pub fn bind<T: FromArgs>(mut self, vm: &VirtualMachine) -> PyResult<T> {
189189
let given_args = self.args.len();
190-
let bound = T::from_args(vm, &mut self).map_err(|e| match e {
191-
ArgumentError::TooFewArgs => vm.new_type_error(format!(
192-
"Expected at least {} arguments ({} given)",
193-
T::arity().start(),
194-
given_args,
195-
)),
196-
ArgumentError::TooManyArgs => vm.new_type_error(format!(
197-
"Expected at most {} arguments ({} given)",
198-
T::arity().end(),
199-
given_args,
200-
)),
201-
ArgumentError::InvalidKeywordArgument(name) => {
202-
vm.new_type_error(format!("{} is an invalid keyword argument", name))
203-
}
204-
ArgumentError::RequiredKeywordArgument(name) => {
205-
vm.new_type_error(format!("Required keyqord only argument {}", name))
206-
}
207-
ArgumentError::Exception(ex) => ex,
208-
})?;
190+
let bound = T::from_args(vm, &mut self)
191+
.map_err(|e| e.into_exception(T::arity(), given_args, vm))?;
209192

210193
if !self.args.is_empty() {
211194
Err(vm.new_type_error(format!(
@@ -243,6 +226,35 @@ impl From<PyBaseExceptionRef> for ArgumentError {
243226
}
244227
}
245228

229+
impl ArgumentError {
230+
fn into_exception(
231+
self,
232+
arity: RangeInclusive<usize>,
233+
num_given: usize,
234+
vm: &VirtualMachine,
235+
) -> PyBaseExceptionRef {
236+
match self {
237+
ArgumentError::TooFewArgs => vm.new_type_error(format!(
238+
"Expected at least {} arguments ({} given)",
239+
arity.start(),
240+
num_given
241+
)),
242+
ArgumentError::TooManyArgs => vm.new_type_error(format!(
243+
"Expected at most {} arguments ({} given)",
244+
arity.end(),
245+
num_given
246+
)),
247+
ArgumentError::InvalidKeywordArgument(name) => {
248+
vm.new_type_error(format!("{} is an invalid keyword argument", name))
249+
}
250+
ArgumentError::RequiredKeywordArgument(name) => {
251+
vm.new_type_error(format!("Required keyqord only argument {}", name))
252+
}
253+
ArgumentError::Exception(ex) => ex,
254+
}
255+
}
256+
}
257+
246258
/// Implemented by any type that can be accepted as a parameter to a built-in
247259
/// function.
248260
///
@@ -439,7 +451,7 @@ impl OptionalArg<PyObjectRef> {
439451
}
440452
}
441453

442-
pub type OptionalOption<T> = OptionalArg<Option<T>>;
454+
pub type OptionalOption<T = PyObjectRef> = OptionalArg<Option<T>>;
443455

444456
impl<T> OptionalOption<T> {
445457
#[inline]

0 commit comments

Comments
 (0)