Skip to content

Commit 0182385

Browse files
committed
py: Automatically ake __new__ a staticmethod.
Addresses issue adafruit#622.
1 parent 4e0eeeb commit 0182385

2 files changed

Lines changed: 23 additions & 3 deletions

File tree

py/objtype.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
#define DEBUG_printf(...) (void)0
4747
#endif
4848

49+
STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args);
50+
4951
/******************************************************************************/
5052
// instance object
5153

@@ -749,6 +751,8 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
749751
assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // Micro Python restriction, for now
750752
assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // Micro Python restriction, for now
751753

754+
// TODO might need to make a copy of locals_dict; at least that's how CPython does it
755+
752756
// Basic validation of base classes
753757
uint len;
754758
mp_obj_t *items;
@@ -783,6 +787,16 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
783787
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict"));
784788
}
785789

790+
mp_map_t *locals_map = mp_obj_dict_get_map(o->locals_dict);
791+
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP);
792+
if (elem != NULL) {
793+
// __new__ slot exists; check if it is a function
794+
if (MP_OBJ_IS_TYPE(elem->value, &mp_type_fun_native) || MP_OBJ_IS_TYPE(elem->value, &mp_type_fun_bc)) {
795+
// __new__ is a function, wrap it in a staticmethod decorator
796+
elem->value = static_class_method_make_new((mp_obj_t)&mp_type_staticmethod, 1, 0, &elem->value);
797+
}
798+
}
799+
786800
return o;
787801
}
788802

tests/basics/class_new.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
class A:
2-
3-
@staticmethod
42
def __new__(cls):
53
print("A.__new__")
64
return super(cls, A).__new__(cls)
@@ -9,13 +7,21 @@ def __init__(self):
97
pass
108

119
def meth(self):
12-
pass
10+
print('A.meth')
1311

1412
#print(A.__new__)
1513
#print(A.__init__)
1614

1715
a = A()
16+
a.meth()
17+
18+
a = A.__new__(A)
19+
a.meth()
1820

1921
#print(a.meth)
2022
#print(a.__init__)
2123
#print(a.__new__)
24+
25+
# __new__ should automatically be a staticmethod, so this should work
26+
a = a.__new__(A)
27+
a.meth()

0 commit comments

Comments
 (0)