Skip to content

Commit d703e26

Browse files
authored
Merge pull request RustPython#3331 from DimitrisJim/relocate_getattribute
Relocate `vm.get_attribute` to `obj.get_attr`
2 parents 7af58dd + 7bc10da commit d703e26

36 files changed

+158
-140
lines changed

src/lib.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,9 @@ fn setup_main_module(vm: &VirtualMachine) -> PyResult<Scope> {
551551
})
552552
.expect("Failed to initialize __main__.__annotations__");
553553

554-
vm.get_attribute(vm.sys_module.clone(), "modules")?
554+
vm.sys_module
555+
.clone()
556+
.get_attr("modules", vm)?
555557
.set_item("__main__", main_module, vm)?;
556558

557559
Ok(scope)
@@ -626,19 +628,19 @@ fn run_command(vm: &VirtualMachine, scope: Scope, source: String) -> PyResult<()
626628
fn run_module(vm: &VirtualMachine, module: &str) -> PyResult<()> {
627629
debug!("Running module {}", module);
628630
let runpy = vm.import("runpy", None, 0)?;
629-
let run_module_as_main = vm.get_attribute(runpy, "_run_module_as_main")?;
631+
let run_module_as_main = runpy.get_attr("_run_module_as_main", vm)?;
630632
vm.invoke(&run_module_as_main, (module,))?;
631633
Ok(())
632634
}
633635

634636
fn get_importer(path: &str, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
635-
let path_importer_cache = vm.get_attribute(vm.sys_module.clone(), "path_importer_cache")?;
637+
let path_importer_cache = vm.sys_module.clone().get_attr("path_importer_cache", vm)?;
636638
let path_importer_cache = PyDictRef::try_from_object(vm, path_importer_cache)?;
637639
if let Some(importer) = path_importer_cache.get_item_option(path, vm)? {
638640
return Ok(Some(importer));
639641
}
640642
let path = vm.ctx.new_str(path);
641-
let path_hooks = vm.get_attribute(vm.sys_module.clone(), "path_hooks")?;
643+
let path_hooks = vm.sys_module.clone().get_attr("path_hooks", vm)?;
642644
let mut importer = None;
643645
let path_hooks: Vec<PyObjectRef> = vm.extract_elements(&path_hooks)?;
644646
for path_hook in path_hooks {
@@ -660,7 +662,7 @@ fn get_importer(path: &str, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>
660662
}
661663

662664
fn insert_sys_path(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<()> {
663-
let sys_path = vm.get_attribute(vm.sys_module.clone(), "path").unwrap();
665+
let sys_path = vm.sys_module.clone().get_attr("path", vm).unwrap();
664666
vm.call_method(&sys_path, "insert", (0, obj))?;
665667
Ok(())
666668
}
@@ -670,7 +672,7 @@ fn run_script(vm: &VirtualMachine, scope: Scope, script_file: &str) -> PyResult<
670672
if get_importer(script_file, vm)?.is_some() {
671673
insert_sys_path(vm, vm.ctx.new_str(script_file).into())?;
672674
let runpy = vm.import("runpy", None, 0)?;
673-
let run_module_as_main = vm.get_attribute(runpy, "_run_module_as_main")?;
675+
let run_module_as_main = runpy.get_attr("_run_module_as_main", vm)?;
674676
vm.invoke(&run_module_as_main, (vm.ctx.new_str("__main__"), false))?;
675677
return Ok(());
676678
}

src/shell.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ pub fn run_shell(vm: &VirtualMachine, scope: Scope) -> PyResult<()> {
5656
loop {
5757
let prompt_name = if continuing { "ps2" } else { "ps1" };
5858
let prompt = vm
59-
.get_attribute(vm.sys_module.clone(), prompt_name)
59+
.sys_module
60+
.clone()
61+
.get_attr(prompt_name, vm)
6062
.and_then(|prompt| vm.to_str(&prompt));
6163
let prompt = match prompt {
6264
Ok(ref s) => s.as_str(),

src/shell/helper.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl<'vm> ShellHelper<'vm> {
7979
.ok()??;
8080

8181
for attr in parents {
82-
current = self.vm.get_attribute(current.clone(), attr.as_str()).ok()?;
82+
current = current.clone().get_attr(attr.as_str(), self.vm).ok()?;
8383
}
8484

8585
let current_iter = str_iter_method(current, "__dir__").ok()?;

stdlib/src/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,7 @@ mod array {
11341134
let code = MachineFormatCode::from_typecode(array.typecode()).unwrap();
11351135
let code = PyInt::from(u8::from(code)).into_object(vm);
11361136
let module = vm.import("array", None, 0)?;
1137-
let func = vm.get_attribute(module, "_array_reconstructor")?;
1137+
let func = module.get_attr("_array_reconstructor", vm)?;
11381138
Ok((
11391139
func,
11401140
vm.new_tuple((cls, typecode, code, bytes)),

stdlib/src/dis.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod decl {
1010

1111
#[pyfunction]
1212
fn dis(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
13-
let co = if let Ok(co) = vm.get_attribute(obj.clone(), "__code__") {
13+
let co = if let Ok(co) = obj.clone().get_attr("__code__", vm) {
1414
// Method or function:
1515
PyRef::try_from_object(vm, co)?
1616
} else if let Ok(co_str) = PyStrRef::try_from_object(vm, obj.clone()) {

stdlib/src/json.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,24 @@ mod _json {
3131
type Args = PyObjectRef;
3232

3333
fn py_new(cls: PyTypeRef, ctx: Self::Args, vm: &VirtualMachine) -> PyResult {
34-
let strict = vm.get_attribute(ctx.clone(), "strict")?.try_to_bool(vm)?;
35-
let object_hook = vm.option_if_none(vm.get_attribute(ctx.clone(), "object_hook")?);
34+
let strict = ctx.clone().get_attr("strict", vm)?.try_to_bool(vm)?;
35+
let object_hook = vm.option_if_none(ctx.clone().get_attr("object_hook", vm)?);
3636
let object_pairs_hook =
37-
vm.option_if_none(vm.get_attribute(ctx.clone(), "object_pairs_hook")?);
38-
let parse_float = vm.get_attribute(ctx.clone(), "parse_float")?;
37+
vm.option_if_none(ctx.clone().get_attr("object_pairs_hook", vm)?);
38+
let parse_float = ctx.clone().get_attr("parse_float", vm)?;
3939
let parse_float =
4040
if vm.is_none(&parse_float) || parse_float.is(&vm.ctx.types.float_type) {
4141
None
4242
} else {
4343
Some(parse_float)
4444
};
45-
let parse_int = vm.get_attribute(ctx.clone(), "parse_int")?;
45+
let parse_int = ctx.clone().get_attr("parse_int", vm)?;
4646
let parse_int = if vm.is_none(&parse_int) || parse_int.is(&vm.ctx.types.int_type) {
4747
None
4848
} else {
4949
Some(parse_int)
5050
};
51-
let parse_constant = vm.get_attribute(ctx.clone(), "parse_constant")?;
51+
let parse_constant = ctx.clone().get_attr("parse_constant", vm)?;
5252

5353
Self {
5454
strict,
@@ -89,7 +89,7 @@ mod _json {
8989
}
9090
'{' => {
9191
// TODO: parse the object in rust
92-
let parse_obj = vm.get_attribute(self.ctx.clone(), "parse_object")?;
92+
let parse_obj = self.ctx.clone().get_attr("parse_object", vm)?;
9393
return PyIterReturn::from_pyresult(
9494
vm.invoke(
9595
&parse_obj,
@@ -106,7 +106,7 @@ mod _json {
106106
}
107107
'[' => {
108108
// TODO: parse the array in rust
109-
let parse_array = vm.get_attribute(self.ctx.clone(), "parse_array")?;
109+
let parse_array = self.ctx.clone().get_attr("parse_array", vm)?;
110110
return PyIterReturn::from_pyresult(
111111
vm.invoke(&parse_array, ((pystr, next_idx), scan_once)),
112112
vm,

stdlib/src/unicodedata.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ use crate::vm::{PyObjectRef, PyValue, VirtualMachine};
66
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
77
let module = unicodedata::make_module(vm);
88

9-
let ucd = unicodedata::Ucd::new(unic_ucd_age::UNICODE_VERSION).into_ref(vm);
9+
let ucd: PyObjectRef = unicodedata::Ucd::new(unic_ucd_age::UNICODE_VERSION)
10+
.into_ref(vm)
11+
.into();
1012

1113
for attr in ["category", "lookup", "name", "bidirectional", "normalize"]
1214
.iter()
1315
.copied()
1416
{
1517
crate::vm::extend_module!(vm, &module, {
16-
attr => vm.get_attribute(ucd.clone().into(), attr).unwrap(),
18+
attr => ucd.clone().get_attr(attr, vm).unwrap(),
1719
});
1820
}
1921

vm/src/builtins/function.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,10 @@ impl PyFunction {
377377

378378
#[pymethod(magic)]
379379
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> String {
380-
let qualname = vm
381-
.get_attribute(zelf.as_object().clone(), "__qualname__")
380+
let qualname = zelf
381+
.as_object()
382+
.clone()
383+
.get_attr("__qualname__", vm)
382384
.ok()
383385
.and_then(|qualname_attr| qualname_attr.downcast::<PyStr>().ok())
384386
.map(|qualname| qualname.as_str().to_owned())
@@ -462,7 +464,7 @@ impl GetAttr for PyBoundMethod {
462464
if let Some(obj) = zelf.get_class_attr(name.as_str()) {
463465
return vm.call_if_get_descriptor(obj, zelf.into());
464466
}
465-
vm.get_attribute(zelf.function.clone(), name)
467+
zelf.function.clone().get_attr(name, vm)
466468
}
467469
}
468470

@@ -520,7 +522,7 @@ impl PyBoundMethod {
520522

521523
#[pyproperty(magic)]
522524
fn doc(&self, vm: &VirtualMachine) -> PyResult {
523-
vm.get_attribute(self.function.clone(), "__doc__")
525+
self.function.clone().get_attr("__doc__", vm)
524526
}
525527

526528
#[pyproperty(magic)]
@@ -535,7 +537,7 @@ impl PyBoundMethod {
535537

536538
#[pyproperty(magic)]
537539
fn module(&self, vm: &VirtualMachine) -> Option<PyObjectRef> {
538-
vm.get_attribute(self.function.clone(), "__module__").ok()
540+
self.function.clone().get_attr("__module__", vm).ok()
539541
}
540542

541543
#[pyproperty(magic)]
@@ -557,8 +559,7 @@ impl PyBoundMethod {
557559
))
558560
.into());
559561
}
560-
561-
vm.get_attribute(self.function.clone(), "__qualname__")
562+
self.function.clone().get_attr("__qualname__", vm)
562563
}
563564
}
564565

vm/src/builtins/function/jitfunc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ pub fn get_jit_arg_types(func: &PyRef<PyFunction>, vm: &VirtualMachine) -> PyRes
8181
return Ok(Vec::new());
8282
}
8383

84-
let annotations = vm.get_attribute(func.clone().into(), "__annotations__")?;
84+
let func_obj: PyObjectRef = func.clone().into();
85+
let annotations = func_obj.get_attr("__annotations__", vm)?;
8586
if vm.is_none(&annotations) {
8687
Err(new_jit_error(
8788
"Jitting function requires arguments to have annotations".to_owned(),

vm/src/builtins/genericalias.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,9 @@ fn make_parameters(args: &PyTupleRef, vm: &VirtualMachine) -> PyTupleRef {
150150
for arg in args.as_slice() {
151151
if is_typevar(arg.clone()) {
152152
parameters.push(arg.clone());
153-
} else if let Ok(tuple) = vm
154-
.get_attribute(arg.clone(), "__parameters__")
153+
} else if let Ok(tuple) = arg
154+
.clone()
155+
.get_attr("__parameters__", vm)
155156
.and_then(|obj| PyTupleRef::try_from_object(vm, obj))
156157
{
157158
for subparam in tuple.as_slice() {
@@ -177,7 +178,7 @@ impl GetAttr for PyGenericAlias {
177178
return vm.generic_getattribute(zelf.as_object().clone(), attr);
178179
}
179180
}
180-
vm.get_attribute(zelf.origin(), attr)
181+
zelf.origin().get_attr(attr, vm)
181182
}
182183
}
183184

vm/src/builtins/iter.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,14 @@ pub fn builtins_iter(vm: &VirtualMachine) -> &PyObjectRef {
147147
static_cell! {
148148
static INSTANCE: PyObjectRef;
149149
}
150-
INSTANCE.get_or_init(|| vm.get_attribute(vm.builtins.clone(), "iter").unwrap())
150+
INSTANCE.get_or_init(|| vm.builtins.clone().get_attr("iter", vm).unwrap())
151151
}
152152

153153
pub fn builtins_reversed(vm: &VirtualMachine) -> &PyObjectRef {
154154
static_cell! {
155155
static INSTANCE: PyObjectRef;
156156
}
157-
INSTANCE.get_or_init(|| vm.get_attribute(vm.builtins.clone(), "reversed").unwrap())
157+
INSTANCE.get_or_init(|| vm.builtins.clone().get_attr("reversed", vm).unwrap())
158158
}
159159

160160
#[pyclass(module = false, name = "iterator")]

vm/src/builtins/module.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl PyModule {
7979
#[pymethod(magic)]
8080
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
8181
let importlib = vm.import("_frozen_importlib", None, 0)?;
82-
let module_repr = vm.get_attribute(importlib, "_module_repr")?;
82+
let module_repr = importlib.get_attr("_module_repr", vm)?;
8383
vm.invoke(&module_repr, (zelf,))
8484
}
8585

vm/src/builtins/object.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,8 @@ impl PyBaseObject {
286286
fn reduce_ex(obj: PyObjectRef, proto: usize, vm: &VirtualMachine) -> PyResult {
287287
if let Some(reduce) = vm.get_attribute_opt(obj.clone(), "__reduce__")? {
288288
let object_reduce = vm.ctx.types.object_type.get_attr("__reduce__").unwrap();
289-
let class_reduce = vm.get_attribute(obj.clone_class().into(), "__reduce__")?;
289+
let typ_obj: PyObjectRef = obj.clone_class().into();
290+
let class_reduce = typ_obj.get_attr("__reduce__", vm)?;
290291
if !class_reduce.is(&object_reduce) {
291292
return vm.invoke(&reduce, ());
292293
}
@@ -364,11 +365,11 @@ pub fn init(ctx: &PyContext) {
364365
fn common_reduce(obj: PyObjectRef, proto: usize, vm: &VirtualMachine) -> PyResult {
365366
if proto >= 2 {
366367
let reducelib = vm.import("__reducelib", None, 0)?;
367-
let reduce_2 = vm.get_attribute(reducelib, "reduce_2")?;
368+
let reduce_2 = reducelib.get_attr("reduce_2", vm)?;
368369
vm.invoke(&reduce_2, (obj,))
369370
} else {
370371
let copyreg = vm.import("copyreg", None, 0)?;
371-
let reduce_ex = vm.get_attribute(copyreg, "_reduce_ex")?;
372+
let reduce_ex = copyreg.get_attr("_reduce_ex", vm)?;
372373
vm.invoke(&reduce_ex, (obj, proto))
373374
}
374375
}

vm/src/builtins/pysuper.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ fn supercheck(ty: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<
186186
if obj.isinstance(&ty) {
187187
return Ok(obj.clone_class());
188188
}
189-
let class_attr = vm.get_attribute(obj, "__class__")?;
189+
let class_attr = obj.get_attr("__class__", vm)?;
190190
if let Ok(cls) = class_attr.downcast::<PyType>() {
191191
if !cls.is(&ty) && cls.issubclass(&ty) {
192192
return Ok(cls);

vm/src/builtins/weakproxy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl PyWeakProxy {
5454
"weakly-referenced object no longer exists".to_owned(),
5555
)
5656
})?;
57-
vm.get_attribute(obj, attr_name)
57+
obj.get_attr(attr_name, vm)
5858
}
5959
}
6060

vm/src/codecs.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,9 @@ fn normalize_encoding_name(encoding: &str) -> Cow<'_, str> {
333333

334334
// TODO: exceptions with custom payloads
335335
fn extract_unicode_error_range(err: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Range<usize>> {
336-
let start = vm.get_attribute(err.clone(), "start")?;
336+
let start = err.clone().get_attr("start", vm)?;
337337
let start = start.try_into_value(vm)?;
338-
let end = vm.get_attribute(err.clone(), "end")?;
338+
let end = err.clone().get_attr("end", vm)?;
339339
let end = end.try_into_value(vm)?;
340340
Ok(Range { start, end })
341341
}
@@ -396,7 +396,7 @@ fn xmlcharrefreplace_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(
396396
return Err(bad_err_type(err, vm));
397397
}
398398
let range = extract_unicode_error_range(&err, vm)?;
399-
let s = PyStrRef::try_from_object(vm, vm.get_attribute(err, "object")?)?;
399+
let s = PyStrRef::try_from_object(vm, err.get_attr("object", vm)?)?;
400400
let s_after_start = crate::common::str::try_get_chars(s.as_str(), range.start..).unwrap_or("");
401401
let num_chars = range.len();
402402
// capacity rough guess; assuming that the codepoints are 3 digits in decimal + the &#;
@@ -411,7 +411,7 @@ fn xmlcharrefreplace_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(
411411
fn backslashreplace_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(String, usize)> {
412412
if is_decode_err(&err, vm) {
413413
let range = extract_unicode_error_range(&err, vm)?;
414-
let b = PyBytesRef::try_from_object(vm, vm.get_attribute(err, "object")?)?;
414+
let b = PyBytesRef::try_from_object(vm, err.get_attr("object", vm)?)?;
415415
let mut replace = String::with_capacity(4 * range.len());
416416
for &c in &b[range.clone()] {
417417
use std::fmt::Write;
@@ -422,7 +422,7 @@ fn backslashreplace_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(S
422422
return Err(bad_err_type(err, vm));
423423
}
424424
let range = extract_unicode_error_range(&err, vm)?;
425-
let s = PyStrRef::try_from_object(vm, vm.get_attribute(err, "object")?)?;
425+
let s = PyStrRef::try_from_object(vm, err.get_attr("object", vm)?)?;
426426
let s_after_start = crate::common::str::try_get_chars(s.as_str(), range.start..).unwrap_or("");
427427
let num_chars = range.len();
428428
// minimum 4 output bytes per char: \xNN
@@ -444,7 +444,7 @@ fn backslashreplace_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(S
444444
fn namereplace_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(String, usize)> {
445445
if err.isinstance(&vm.ctx.exceptions.unicode_encode_error) {
446446
let range = extract_unicode_error_range(&err, vm)?;
447-
let s = PyStrRef::try_from_object(vm, vm.get_attribute(err, "object")?)?;
447+
let s = PyStrRef::try_from_object(vm, err.get_attr("object", vm)?)?;
448448
let s_after_start =
449449
crate::common::str::try_get_chars(s.as_str(), range.start..).unwrap_or("");
450450
let num_chars = range.len();
@@ -539,8 +539,8 @@ fn get_standard_encoding(encoding: &str) -> (usize, StandardEncoding) {
539539
fn surrogatepass_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(String, usize)> {
540540
if err.isinstance(&vm.ctx.exceptions.unicode_encode_error) {
541541
let range = extract_unicode_error_range(&err, vm)?;
542-
let s = PyStrRef::try_from_object(vm, vm.get_attribute(err.clone(), "object")?)?;
543-
let s_encoding = PyStrRef::try_from_object(vm, vm.get_attribute(err.clone(), "encoding")?)?;
542+
let s = PyStrRef::try_from_object(vm, err.clone().get_attr("object", vm)?)?;
543+
let s_encoding = PyStrRef::try_from_object(vm, err.clone().get_attr("encoding", vm)?)?;
544544
let (_, standard_encoding) = get_standard_encoding(s_encoding.as_str());
545545
if let StandardEncoding::Unknown = standard_encoding {
546546
// Not supported, fail with original exception
@@ -590,8 +590,8 @@ fn surrogatepass_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(Stri
590590
Ok((out, range.end))
591591
} else if is_decode_err(&err, vm) {
592592
let range = extract_unicode_error_range(&err, vm)?;
593-
let s = PyStrRef::try_from_object(vm, vm.get_attribute(err.clone(), "object")?)?;
594-
let s_encoding = PyStrRef::try_from_object(vm, vm.get_attribute(err.clone(), "encoding")?)?;
593+
let s = PyStrRef::try_from_object(vm, err.clone().get_attr("object", vm)?)?;
594+
let s_encoding = PyStrRef::try_from_object(vm, err.clone().get_attr("encoding", vm)?)?;
595595
let (byte_length, standard_encoding) = get_standard_encoding(s_encoding.as_str());
596596
if let StandardEncoding::Unknown = standard_encoding {
597597
// Not supported, fail with original exception
@@ -652,7 +652,7 @@ fn surrogatepass_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(Stri
652652
fn surrogateescape_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(String, usize)> {
653653
if err.isinstance(&vm.ctx.exceptions.unicode_encode_error) {
654654
let range = extract_unicode_error_range(&err, vm)?;
655-
let s = PyStrRef::try_from_object(vm, vm.get_attribute(err.clone(), "object")?)?;
655+
let s = PyStrRef::try_from_object(vm, err.clone().get_attr("object", vm)?)?;
656656
let s_after_start =
657657
crate::common::str::try_get_chars(s.as_str(), range.start..).unwrap_or("");
658658
let num_chars = range.len();
@@ -668,7 +668,7 @@ fn surrogateescape_errors(err: PyObjectRef, vm: &VirtualMachine) -> PyResult<(St
668668
Ok((out, range.end))
669669
} else if is_decode_err(&err, vm) {
670670
let range = extract_unicode_error_range(&err, vm)?;
671-
let s = PyStrRef::try_from_object(vm, vm.get_attribute(err.clone(), "object")?)?;
671+
let s = PyStrRef::try_from_object(vm, err.clone().get_attr("object", vm)?)?;
672672
let s_after_start = crate::common::str::try_get_chars(s.as_str(), range.start..)
673673
.unwrap_or("")
674674
.as_bytes();

0 commit comments

Comments
 (0)