Skip to content

Commit 64131f3

Browse files
committed
Add staticmethod and classmethod to builtin namespace.
1 parent ddaf6c1 commit 64131f3

4 files changed

Lines changed: 38 additions & 20 deletions

File tree

py/obj.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
6666
// These macros are used to declare and define constant staticmethond and classmethod objects
6767
// You can put "static" in front of the definitions to make them local
6868

69-
#define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_obj_staticmethod_t obj_name
70-
#define MP_DECLARE_CONST_CLASSMETHOD_OBJ(obj_name) extern const mp_obj_classmethod_t obj_name
69+
#define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_obj_static_class_method_t obj_name
70+
#define MP_DECLARE_CONST_CLASSMETHOD_OBJ(obj_name) extern const mp_obj_static_class_method_t obj_name
7171

72-
#define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_obj_staticmethod_t obj_name = {{&mp_type_staticmethod}, fun_name}
73-
#define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_obj_classmethod_t obj_name = {{&mp_type_classmethod}, fun_name}
72+
#define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_obj_static_class_method_t obj_name = {{&mp_type_staticmethod}, fun_name}
73+
#define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_obj_static_class_method_t obj_name = {{&mp_type_classmethod}, fun_name}
7474

7575
// Need to declare this here so we are not dependent on map.h
7676
struct _mp_map_t;
@@ -180,7 +180,6 @@ struct _mp_obj_type_t {
180180
abs float complex
181181
hash bool int none str
182182
equal int str
183-
less int
184183
get_array_n tuple list
185184
186185
unpack seq list tuple
@@ -389,15 +388,11 @@ struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in);
389388
extern const mp_obj_type_t mp_type_staticmethod;
390389
extern const mp_obj_type_t mp_type_classmethod;
391390

392-
typedef struct _mp_obj_staticmethod_t {
391+
// this structure is used for instances of both staticmethod and classmethod
392+
typedef struct _mp_obj_static_class_method_t {
393393
mp_obj_base_t base;
394394
mp_obj_t fun;
395-
} mp_obj_staticmethod_t;
396-
397-
typedef struct _mp_obj_classmethod_t {
398-
mp_obj_base_t base;
399-
mp_obj_t fun;
400-
} mp_obj_classmethod_t;
395+
} mp_obj_static_class_method_t;
401396

402397
// sequence helpers
403398
void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest);

py/objtype.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,10 @@ static void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
212212
// TODO check that this is the correct place to have this logic
213213
if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
214214
// return just the function
215-
dest[0] = ((mp_obj_staticmethod_t*)member)->fun;
215+
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
216216
} else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
217217
// return a bound method, with self being the type of this object
218-
dest[0] = ((mp_obj_classmethod_t*)member)->fun;
218+
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
219219
dest[1] = mp_obj_get_type(self_in);
220220
} else {
221221
// return a bound method, with self being this object
@@ -304,10 +304,10 @@ static void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
304304
// see http://docs.python.org/3.3/howto/descriptor.html
305305
if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
306306
// return just the function
307-
dest[0] = ((mp_obj_staticmethod_t*)member)->fun;
307+
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
308308
} else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
309309
// return a bound method, with self being this class
310-
dest[0] = ((mp_obj_classmethod_t*)member)->fun;
310+
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
311311
dest[1] = self_in;
312312
} else {
313313
// return just the function
@@ -417,10 +417,10 @@ static void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
417417
// TODO check that this is the correct place to have this logic
418418
if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
419419
// return just the function
420-
dest[0] = ((mp_obj_staticmethod_t*)member)->fun;
420+
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
421421
} else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
422422
// return a bound method, with self being the type of this object
423-
dest[0] = ((mp_obj_classmethod_t*)member)->fun;
423+
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
424424
dest[1] = mp_obj_get_type(self->obj);
425425
} else {
426426
// return a bound method, with self being this object
@@ -507,12 +507,26 @@ MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
507507
/******************************************************************************/
508508
// staticmethod and classmethod types (probably should go in a different file)
509509

510+
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) {
511+
assert(self_in == &mp_type_staticmethod || self_in == &mp_type_classmethod);
512+
513+
if (n_args != 1 || n_kw != 0) {
514+
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "function takes 1 positional argument but %d were given", (void*)(machine_int_t)n_args));
515+
}
516+
517+
mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t);
518+
*o = (mp_obj_static_class_method_t){{(mp_obj_type_t*)self_in}, args[0]};
519+
return o;
520+
}
521+
510522
const mp_obj_type_t mp_type_staticmethod = {
511523
{ &mp_const_type },
512524
"staticmethod",
525+
.make_new = static_class_method_make_new
513526
};
514527

515528
const mp_obj_type_t mp_type_classmethod = {
516529
{ &mp_const_type },
517530
"classmethod",
531+
.make_new = static_class_method_make_new
518532
};

py/qstrdefs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Q(bytearray)
5151
Q(bytes)
5252
Q(callable)
5353
Q(chr)
54+
Q(classmethod)
5455
Q(complex)
5556
Q(dict)
5657
Q(dir)
@@ -80,6 +81,7 @@ Q(range)
8081
Q(repr)
8182
Q(set)
8283
Q(sorted)
84+
Q(staticmethod)
8385
Q(sum)
8486
Q(super)
8587
Q(str)

py/runtime.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ void rt_init(void) {
134134
mp_map_add_qstr(&map_builtins, MP_QSTR_type, (mp_obj_t)&mp_const_type);
135135
mp_map_add_qstr(&map_builtins, MP_QSTR_zip, (mp_obj_t)&zip_type);
136136

137+
mp_map_add_qstr(&map_builtins, MP_QSTR_classmethod, (mp_obj_t)&mp_type_classmethod);
138+
mp_map_add_qstr(&map_builtins, MP_QSTR_staticmethod, (mp_obj_t)&mp_type_staticmethod);
139+
137140
mp_obj_t m_array = mp_obj_new_module(MP_QSTR_array);
138141
rt_store_attr(m_array, MP_QSTR_array, (mp_obj_t)&array_type);
139142

@@ -876,10 +879,10 @@ static void rt_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest) {
876879
// see http://docs.python.org/3.3/howto/descriptor.html
877880
if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_staticmethod)) {
878881
// return just the function
879-
dest[0] = ((mp_obj_staticmethod_t*)meth->fun)->fun;
882+
dest[0] = ((mp_obj_static_class_method_t*)meth->fun)->fun;
880883
} else if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_classmethod)) {
881884
// return a bound method, with self being the type of this object
882-
dest[0] = ((mp_obj_classmethod_t*)meth->fun)->fun;
885+
dest[0] = ((mp_obj_static_class_method_t*)meth->fun)->fun;
883886
dest[1] = mp_obj_get_type(base);
884887
} else {
885888
// return a bound method, with self being this object
@@ -970,6 +973,8 @@ mp_obj_t rt_iternext(mp_obj_t o_in) {
970973
}
971974

972975
mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {
976+
DEBUG_printf("import name %s\n", qstr_str(name));
977+
973978
// build args array
974979
mp_obj_t args[5];
975980
args[0] = MP_OBJ_NEW_QSTR(name);
@@ -983,6 +988,8 @@ mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {
983988
}
984989

985990
mp_obj_t rt_import_from(mp_obj_t module, qstr name) {
991+
DEBUG_printf("import from %p %s\n", module, qstr_str(name));
992+
986993
mp_obj_t x = rt_load_attr(module, name);
987994
/* TODO convert AttributeError to ImportError
988995
if (fail) {

0 commit comments

Comments
 (0)