Skip to content

Commit 7cf9323

Browse files
committed
py/obj: Add support for __float__ converter function.
1 parent 6519b1b commit 7cf9323

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

py/obj.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ const mp_obj_type_t *MICROPY_WRAP_MP_OBJ_GET_TYPE(mp_obj_get_type)(mp_const_obj_
6767
} else if (mp_obj_is_obj(o_in)) {
6868
const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in);
6969
return o->type;
70-
#if MICROPY_PY_BUILTINS_FLOAT
70+
#if MICROPY_PY_BUILTINS_FLOAT
7171
} else if ((((mp_uint_t)(o_in)) & 0xff800007) != 0x00000006) {
7272
return &mp_type_float;
73-
#endif
73+
#endif
7474
} else {
7575
static const mp_obj_type_t *const types[] = {
7676
&mp_type_str, &mp_type_NoneType, &mp_type_str, &mp_type_bool,
@@ -89,11 +89,11 @@ const mp_obj_type_t *MICROPY_WRAP_MP_OBJ_GET_TYPE(mp_obj_get_type)(mp_const_obj_
8989
} else if (mp_obj_is_float(o_in)) {
9090
return &mp_type_float;
9191
#endif
92-
#if MICROPY_OBJ_IMMEDIATE_OBJS
92+
#if MICROPY_OBJ_IMMEDIATE_OBJS
9393
} else if (mp_obj_is_immediate_obj(o_in)) {
9494
static const mp_obj_type_t *const types[2] = {&mp_type_NoneType, &mp_type_bool};
9595
return types[MP_OBJ_IMMEDIATE_OBJ_VALUE(o_in) & 1];
96-
#endif
96+
#endif
9797
} else {
9898
const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in);
9999
return o->type;
@@ -225,20 +225,20 @@ mp_obj_t mp_obj_equal_not_equal(mp_binary_op_t op, mp_obj_t o1, mp_obj_t o2) {
225225
if (mp_obj_is_str(o2)) {
226226
// both strings, use special function
227227
return mp_obj_str_equal(o1, o2) ? local_true : local_false;
228-
#if MICROPY_PY_STR_BYTES_CMP_WARN
228+
#if MICROPY_PY_STR_BYTES_CMP_WARN
229229
} else if (mp_obj_is_type(o2, &mp_type_bytes)) {
230230
str_bytes_cmp:
231231
mp_warning(MP_WARN_CAT(BytesWarning), "Comparison between bytes and str");
232232
return local_false;
233-
#endif
233+
#endif
234234
} else {
235235
goto skip_one_pass;
236236
}
237-
#if MICROPY_PY_STR_BYTES_CMP_WARN
237+
#if MICROPY_PY_STR_BYTES_CMP_WARN
238238
} else if (mp_obj_is_str(o2) && mp_obj_is_type(o1, &mp_type_bytes)) {
239239
// o1 is not a string (else caught above), so the objects are not equal
240240
goto str_bytes_cmp;
241-
#endif
241+
#endif
242242
}
243243

244244
// fast path for small ints
@@ -348,14 +348,21 @@ bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value) {
348348
val = 1;
349349
} else if (mp_obj_is_small_int(arg)) {
350350
val = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg);
351-
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
351+
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
352352
} else if (mp_obj_is_type(arg, &mp_type_int)) {
353353
val = mp_obj_int_as_float_impl(arg);
354-
#endif
354+
#endif
355355
} else if (mp_obj_is_float(arg)) {
356356
val = mp_obj_float_get(arg);
357357
} else {
358-
return false;
358+
// Call __float__() function if it exists.
359+
mp_obj_t dest[2];
360+
mp_load_method_maybe(arg, MP_QSTR___float__, dest);
361+
if (dest[0] == MP_OBJ_NULL) {
362+
// No conversion to float available
363+
return false;
364+
}
365+
val = mp_obj_float_get(mp_call_method_n_kw(0, 0, dest));
359366
}
360367

361368
*value = val;
@@ -388,11 +395,11 @@ bool mp_obj_get_complex_maybe(mp_obj_t arg, mp_float_t *real, mp_float_t *imag)
388395
} else if (mp_obj_is_small_int(arg)) {
389396
*real = (mp_float_t)MP_OBJ_SMALL_INT_VALUE(arg);
390397
*imag = 0;
391-
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
398+
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
392399
} else if (mp_obj_is_type(arg, &mp_type_int)) {
393400
*real = mp_obj_int_as_float_impl(arg);
394401
*imag = 0;
395-
#endif
402+
#endif
396403
} else if (mp_obj_is_float(arg)) {
397404
*real = mp_obj_float_get(arg);
398405
*imag = 0;

tests/float/float_dunder.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# test __float__ function support
2+
3+
class TestFloat():
4+
def __float__(self):
5+
return 10.0
6+
7+
8+
class Test():
9+
pass
10+
11+
12+
print("%.1f" % float(TestFloat()))
13+
14+
try:
15+
print(float(Test()))
16+
except TypeError:
17+
print("TypeError")

0 commit comments

Comments
 (0)