Skip to content

Commit 21e6910

Browse files
committed
Misc wrong behavior for function props, module.__init__, type.getattro
1 parent 4129f0c commit 21e6910

File tree

6 files changed

+54
-23
lines changed

6 files changed

+54
-23
lines changed

Lib/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def _m(self): pass
5353

5454
# For Jython, the following two types are identical
5555
GetSetDescriptorType = type(FunctionType.__code__)
56-
# MemberDescriptorType = type(FunctionType.__globals__)
56+
MemberDescriptorType = type(FunctionType.__globals__)
5757

5858
del sys, _f, _g, _C # Not for export
5959

vm/src/builtins/function.rs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ pub struct PyFunction {
3838
jitted_code: OnceCell<CompiledCode>,
3939
globals: PyDictRef,
4040
closure: Option<PyTupleTyped<PyCellRef>>,
41-
defaults: Option<PyTupleRef>,
42-
kw_only_defaults: Option<PyDictRef>,
41+
defaults_and_kwdefaults: PyMutex<(Option<PyTupleRef>, Option<PyDictRef>)>,
4342
name: PyMutex<PyStrRef>,
4443
}
4544

@@ -58,8 +57,7 @@ impl PyFunction {
5857
jitted_code: OnceCell::new(),
5958
globals,
6059
closure,
61-
defaults,
62-
kw_only_defaults,
60+
defaults_and_kwdefaults: PyMutex::new((defaults, kw_only_defaults)),
6361
name,
6462
}
6563
}
@@ -161,10 +159,20 @@ impl PyFunction {
161159
)));
162160
}
163161

162+
let mut defaults_and_kwdefaults = None;
163+
// can't be a closure cause it returns a reference to a captured variable :/
164+
macro_rules! get_defaults {
165+
() => {{
166+
defaults_and_kwdefaults
167+
.get_or_insert_with(|| self.defaults_and_kwdefaults.lock().clone())
168+
}};
169+
}
170+
164171
// Add missing positional arguments, if we have fewer positional arguments than the
165172
// function definition calls for
166173
if nargs < nexpected_args {
167-
let ndefs = self.defaults.as_ref().map_or(0, |d| d.borrow_value().len());
174+
let defaults = get_defaults!().0.as_ref().map(|tup| tup.borrow_value());
175+
let ndefs = defaults.map_or(0, |d| d.len());
168176

169177
let nrequired = code.arg_count - ndefs;
170178

@@ -184,9 +192,7 @@ impl PyFunction {
184192
)));
185193
}
186194

187-
if let Some(defaults) = &self.defaults {
188-
let defaults = defaults.borrow_value();
189-
195+
if let Some(defaults) = defaults {
190196
let n = std::cmp::min(nargs, nexpected_args);
191197
let i = n.saturating_sub(nrequired);
192198

@@ -212,10 +218,8 @@ impl PyFunction {
212218
.take(code.kwonlyarg_count)
213219
{
214220
if slot.is_none() {
215-
if let Some(kw_only_defaults) = &self.kw_only_defaults {
216-
if let Some(default) =
217-
kw_only_defaults.get_item_option(kwarg.clone(), vm)?
218-
{
221+
if let Some(defaults) = &get_defaults!().1 {
222+
if let Some(default) = defaults.get_item_option(kwarg.clone(), vm)? {
219223
*slot = Some(default);
220224
continue;
221225
}
@@ -311,12 +315,20 @@ impl PyFunction {
311315

312316
#[pyproperty(magic)]
313317
fn defaults(&self) -> Option<PyTupleRef> {
314-
self.defaults.clone()
318+
self.defaults_and_kwdefaults.lock().0.clone()
319+
}
320+
#[pyproperty(magic, setter)]
321+
fn set_defaults(&self, defaults: Option<PyTupleRef>) {
322+
self.defaults_and_kwdefaults.lock().0 = defaults
315323
}
316324

317325
#[pyproperty(magic)]
318326
fn kwdefaults(&self) -> Option<PyDictRef> {
319-
self.kw_only_defaults.clone()
327+
self.defaults_and_kwdefaults.lock().1.clone()
328+
}
329+
#[pyproperty(magic, setter)]
330+
fn set_kwdefaults(&self, kwdefaults: Option<PyDictRef>) {
331+
self.defaults_and_kwdefaults.lock().1 = kwdefaults
320332
}
321333

322334
#[pyproperty(magic)]
@@ -425,6 +437,16 @@ impl PyBoundMethod {
425437
PyBoundMethod { object, function }
426438
}
427439

440+
#[pyslot]
441+
fn tp_new(
442+
cls: PyTypeRef,
443+
function: PyObjectRef,
444+
object: PyObjectRef,
445+
vm: &VirtualMachine,
446+
) -> PyResult<PyRef<Self>> {
447+
PyBoundMethod::new(object, function).into_ref_with_type(vm, cls)
448+
}
449+
428450
#[pymethod(magic)]
429451
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
430452
Ok(format!(

vm/src/builtins/function/jitfunc.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,10 @@ pub(crate) fn get_jit_args<'a>(
169169
}
170170
}
171171

172+
let (defaults, kwdefaults) = func.defaults_and_kwdefaults.lock().clone();
173+
172174
// fill in positional defaults
173-
if let Some(defaults) = &func.defaults {
175+
if let Some(defaults) = defaults {
174176
let defaults = defaults.borrow_value();
175177
for (i, default) in defaults.iter().enumerate() {
176178
let arg_idx = i + func.code.arg_count - defaults.len();
@@ -181,7 +183,7 @@ pub(crate) fn get_jit_args<'a>(
181183
}
182184

183185
// fill in keyword only defaults
184-
if let Some(kw_only_defaults) = &func.kw_only_defaults {
186+
if let Some(kw_only_defaults) = kwdefaults {
185187
for (i, name) in arg_names.kwonlyargs.iter().enumerate() {
186188
let arg_idx = i + func.code.arg_count;
187189
if !jit_args.is_set(arg_idx) {

vm/src/builtins/module.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::dict::PyDictRef;
22
use super::pystr::{PyStr, PyStrRef};
33
use super::pytype::PyTypeRef;
4-
use crate::function::{FuncArgs, OptionalOption};
4+
use crate::function::FuncArgs;
55
use crate::pyobject::{
66
BorrowValue, IntoPyObject, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult,
77
PyValue,
@@ -43,6 +43,14 @@ pub fn init_module_dict(
4343
.expect("Failed to set __spec__ on module");
4444
}
4545

46+
#[derive(FromArgs)]
47+
struct ModuleInitArgs {
48+
#[pyarg(any)]
49+
name: PyStrRef,
50+
#[pyarg(any, default)]
51+
doc: Option<PyStrRef>,
52+
}
53+
4654
#[pyimpl(with(SlotGetattro), flags(BASETYPE, HAS_DICT))]
4755
impl PyModule {
4856
#[pyslot]
@@ -51,16 +59,16 @@ impl PyModule {
5159
}
5260

5361
#[pymethod(magic)]
54-
fn init(zelf: PyRef<Self>, name: PyStrRef, doc: OptionalOption<PyStrRef>, vm: &VirtualMachine) {
62+
fn init(zelf: PyRef<Self>, args: ModuleInitArgs, vm: &VirtualMachine) {
5563
debug_assert!(crate::pyobject::TypeProtocol::class(zelf.as_object())
5664
.slots
5765
.flags
5866
.has_feature(crate::slots::PyTpFlags::HAS_DICT));
5967
init_module_dict(
6068
vm,
6169
&zelf.as_object().dict().unwrap(),
62-
name.into_object(),
63-
doc.flatten().into_pyobject(vm),
70+
args.name.into_object(),
71+
args.doc.into_pyobject(vm),
6472
);
6573
}
6674

vm/src/builtins/pytype.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,6 @@ impl SlotGetattro for PyType {
536536
} else if let Some(attr) = mcl_attr {
537537
drop(mcl);
538538
vm.call_if_get_descriptor(attr, zelf.into_object())
539-
} else if let Some(ref getter) = zelf.get_attr("__getattr__") {
540-
vm.invoke(getter, (PyLease::into_pyref(mcl), name_str))
541539
} else {
542540
Err(vm.new_attribute_error(format!(
543541
"type object '{}' has no attribute '{}'",

vm/src/stdlib/signal.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
164164
"SIGINT" => ctx.new_int(libc::SIGINT as u8),
165165
"SIGSEGV" => ctx.new_int(libc::SIGSEGV as u8),
166166
"SIGTERM" => ctx.new_int(libc::SIGTERM as u8),
167+
"NSIG" => ctx.new_int(NSIG),
167168
"default_int_handler" => int_handler.clone(),
168169
});
169170
extend_module_platform_specific(vm, &module);

0 commit comments

Comments
 (0)