Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 18ceb70

Browse files
committed
Merge branch 'master' of github.com:micropython/micropython
2 parents a7a1a38 + eea0118 commit 18ceb70

14 files changed

+175
-17
lines changed

py/obj.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,18 @@
3636
#include "runtime0.h"
3737
#include "runtime.h"
3838

39-
mp_obj_type_t *mp_obj_get_type(mp_obj_t o_in) {
39+
mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) {
4040
if (MP_OBJ_IS_SMALL_INT(o_in)) {
4141
return (mp_obj_t)&mp_type_int;
4242
} else if (MP_OBJ_IS_QSTR(o_in)) {
4343
return (mp_obj_t)&mp_type_str;
4444
} else {
45-
mp_obj_base_t *o = o_in;
45+
const mp_obj_base_t *o = o_in;
4646
return (mp_obj_t)o->type;
4747
}
4848
}
4949

50-
const char *mp_obj_get_type_str(mp_obj_t o_in) {
50+
const char *mp_obj_get_type_str(mp_const_obj_t o_in) {
5151
return qstr_str(mp_obj_get_type(o_in)->name);
5252
}
5353

py/obj.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,10 @@ mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self);
398398
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args);
399399
mp_obj_t mp_obj_new_module(qstr module_name);
400400

401-
mp_obj_type_t *mp_obj_get_type(mp_obj_t o_in);
402-
const char *mp_obj_get_type_str(mp_obj_t o_in);
401+
mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in);
402+
const char *mp_obj_get_type_str(mp_const_obj_t o_in);
403403
bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects
404+
mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type);
404405

405406
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind);
406407
void mp_obj_print(mp_obj_t o, mp_print_kind_t kind);

py/objboundmeth.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ typedef struct _mp_obj_bound_meth_t {
3939
mp_obj_t self;
4040
} mp_obj_bound_meth_t;
4141

42+
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
43+
STATIC void bound_meth_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
44+
mp_obj_bound_meth_t *o = o_in;
45+
print(env, "<bound_method %p ", o);
46+
mp_obj_print_helper(print, env, o->self, PRINT_REPR);
47+
print(env, ".");
48+
mp_obj_print_helper(print, env, o->meth, PRINT_REPR);
49+
print(env, ">");
50+
}
51+
#endif
52+
4253
mp_obj_t bound_meth_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
4354
mp_obj_bound_meth_t *self = self_in;
4455

@@ -65,6 +76,9 @@ mp_obj_t bound_meth_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_
6576
const mp_obj_type_t bound_meth_type = {
6677
{ &mp_type_type },
6778
.name = MP_QSTR_bound_method,
79+
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
80+
.print = bound_meth_print,
81+
#endif
6882
.call = bound_meth_call,
6983
};
7084

py/objlist.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,24 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
153153
STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
154154
if (value == MP_OBJ_NULL) {
155155
// delete
156+
#if MICROPY_ENABLE_SLICE
157+
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
158+
mp_obj_list_t *self = self_in;
159+
machine_uint_t start, stop;
160+
if (!mp_seq_get_fast_slice_indexes(self->len, index, &start, &stop)) {
161+
assert(0);
162+
}
163+
164+
int len_adj = start - stop;
165+
//printf("Len adj: %d\n", len_adj);
166+
assert(len_adj <= 0);
167+
mp_seq_replace_slice_no_grow(self->items, self->len, start, stop, self->items/*NULL*/, 0, mp_obj_t);
168+
// Clear "freed" elements at the end of list
169+
mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
170+
self->len += len_adj;
171+
return mp_const_none;
172+
}
173+
#endif
156174
mp_obj_t args[2] = {self_in, index};
157175
list_pop(2, args);
158176
return mp_const_none;

py/objstr.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
5454
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str);
5555
STATIC mp_obj_t str_new(const mp_obj_type_t *type, const byte* data, uint len);
5656
STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
57+
STATIC NORETURN void arg_type_mixup();
58+
59+
STATIC bool is_str_or_bytes(mp_obj_t o) {
60+
return MP_OBJ_IS_STR(o) || MP_OBJ_IS_TYPE(o, &mp_type_bytes);
61+
}
5762

5863
/******************************************************************************/
5964
/* str */
@@ -535,7 +540,8 @@ enum { LSTRIP, RSTRIP, STRIP };
535540

536541
STATIC mp_obj_t str_uni_strip(int type, uint n_args, const mp_obj_t *args) {
537542
assert(1 <= n_args && n_args <= 2);
538-
assert(MP_OBJ_IS_STR(args[0]));
543+
assert(is_str_or_bytes(args[0]));
544+
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
539545

540546
const byte *chars_to_del;
541547
uint chars_to_del_len;
@@ -545,7 +551,9 @@ STATIC mp_obj_t str_uni_strip(int type, uint n_args, const mp_obj_t *args) {
545551
chars_to_del = whitespace;
546552
chars_to_del_len = sizeof(whitespace);
547553
} else {
548-
assert(MP_OBJ_IS_STR(args[1]));
554+
if (mp_obj_get_type(args[1]) != self_type) {
555+
arg_type_mixup();
556+
}
549557
GET_STR_DATA_LEN(args[1], s, l);
550558
chars_to_del = s;
551559
chars_to_del_len = l;
@@ -589,7 +597,7 @@ STATIC mp_obj_t str_uni_strip(int type, uint n_args, const mp_obj_t *args) {
589597
assert(last_good_char_pos >= first_good_char_pos);
590598
//+1 to accomodate the last character
591599
machine_uint_t stripped_len = last_good_char_pos - first_good_char_pos + 1;
592-
return mp_obj_new_str(orig_str + first_good_char_pos, stripped_len, false);
600+
return str_new(self_type, orig_str + first_good_char_pos, stripped_len);
593601
}
594602

595603
STATIC mp_obj_t str_strip(uint n_args, const mp_obj_t *args) {
@@ -1326,9 +1334,12 @@ STATIC mp_obj_t str_count(uint n_args, const mp_obj_t *args) {
13261334
}
13271335

13281336
STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t direction) {
1329-
assert(MP_OBJ_IS_STR(self_in));
1330-
if (!MP_OBJ_IS_STR(arg)) {
1331-
bad_implicit_conversion(arg);
1337+
if (!is_str_or_bytes(self_in)) {
1338+
assert(0);
1339+
}
1340+
mp_obj_type_t *self_type = mp_obj_get_type(self_in);
1341+
if (self_type != mp_obj_get_type(arg)) {
1342+
arg_type_mixup();
13321343
}
13331344

13341345
GET_STR_DATA_LEN(self_in, str, str_len);
@@ -1349,9 +1360,9 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t di
13491360
const byte *position_ptr = find_subbytes(str, str_len, sep, sep_len, direction);
13501361
if (position_ptr != NULL) {
13511362
machine_uint_t position = position_ptr - str;
1352-
result[0] = mp_obj_new_str(str, position, false);
1363+
result[0] = str_new(self_type, str, position);
13531364
result[1] = arg;
1354-
result[2] = mp_obj_new_str(str + position + sep_len, str_len - position - sep_len, false);
1365+
result[2] = str_new(self_type, str + position + sep_len, str_len - position - sep_len);
13551366
}
13561367

13571368
return mp_obj_new_tuple(3, result);
@@ -1586,6 +1597,10 @@ STATIC void bad_implicit_conversion(mp_obj_t self_in) {
15861597
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in)));
15871598
}
15881599

1600+
STATIC void arg_type_mixup() {
1601+
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Can't mix str and bytes arguments"));
1602+
}
1603+
15891604
uint mp_obj_str_get_hash(mp_obj_t self_in) {
15901605
// TODO: This has too big overhead for hash accessor
15911606
if (MP_OBJ_IS_STR(self_in) || MP_OBJ_IS_TYPE(self_in, &mp_type_bytes)) {
@@ -1632,7 +1647,7 @@ const char *mp_obj_str_get_str(mp_obj_t self_in) {
16321647
}
16331648

16341649
const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len) {
1635-
if (MP_OBJ_IS_STR(self_in)) {
1650+
if (is_str_or_bytes(self_in)) {
16361651
GET_STR_DATA_LEN(self_in, s, l);
16371652
*len = l;
16381653
return (const char*)s;

py/objtuple.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,20 @@ mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
9999

100100
// Don't pass MP_BINARY_OP_NOT_EQUAL here
101101
STATIC bool tuple_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) {
102-
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
103-
if (!MP_OBJ_IS_TYPE(another_in, &mp_type_tuple)) {
104-
return false;
102+
mp_obj_type_t *self_type = mp_obj_get_type(self_in);
103+
if (self_type->getiter != tuple_getiter) {
104+
assert(0);
105105
}
106+
mp_obj_type_t *another_type = mp_obj_get_type(another_in);
106107
mp_obj_tuple_t *self = self_in;
107108
mp_obj_tuple_t *another = another_in;
109+
if (another_type->getiter != tuple_getiter) {
110+
// Slow path for user subclasses
111+
another = mp_instance_cast_to_native_base(another, &mp_type_tuple);
112+
if (another == MP_OBJ_NULL) {
113+
return false;
114+
}
115+
}
108116

109117
return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
110118
}

py/objtype.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ STATIC void instance_convert_return_attr(mp_obj_t self, mp_obj_t member, mp_obj_
333333
// return a bound method, with self being the type of this object
334334
dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
335335
dest[1] = mp_obj_get_type(self);
336+
} else if (MP_OBJ_IS_TYPE(member, &mp_type_type)) {
337+
// Don't try to bind types
338+
dest[0] = member;
336339
} else if (mp_obj_is_callable(member)) {
337340
// return a bound method, with self being this object
338341
dest[0] = member;
@@ -842,6 +845,15 @@ STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
842845

843846
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
844847

848+
mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type) {
849+
mp_obj_type_t *self_type = mp_obj_get_type(self_in);
850+
if (!mp_obj_is_subclass_fast(self_type, native_type)) {
851+
return MP_OBJ_NULL;
852+
}
853+
mp_obj_instance_t *self = (mp_obj_instance_t*)self_in;
854+
return self->subobj[0];
855+
}
856+
845857
/******************************************************************************/
846858
// staticmethod and classmethod types (probably should go in a different file)
847859

py/runtime.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,9 @@ void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest) {
840840
// return a bound method, with self being the type of this object
841841
dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun;
842842
dest[1] = mp_obj_get_type(base);
843+
} else if (MP_OBJ_IS_TYPE(elem->value, &mp_type_type)) {
844+
// Don't try to bind types
845+
dest[0] = elem->value;
843846
} else if (mp_obj_is_callable(elem->value)) {
844847
// return a bound method, with self being this object
845848
dest[0] = elem->value;

tests/basics/class_store_class.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Inspired by urlparse.py from CPython 3.3 stdlib
2+
# There was a bug in MicroPython that under some conditions class stored
3+
# in instance attribute later was returned "bound" as if it was a method,
4+
# which caused class constructor to receive extra argument.
5+
try:
6+
from collections import namedtuple
7+
except ImportError:
8+
from _collections import namedtuple
9+
10+
_DefragResultBase = namedtuple('DefragResult', 'foo bar')
11+
12+
class _ResultMixinStr(object):
13+
def encode(self):
14+
return self._encoded_counterpart(*(x.encode() for x in self))
15+
16+
class _ResultMixinBytes(object):
17+
def decode(self):
18+
return self._decoded_counterpart(*(x.decode() for x in self))
19+
20+
class DefragResult(_DefragResultBase, _ResultMixinStr):
21+
pass
22+
23+
class DefragResultBytes(_DefragResultBase, _ResultMixinBytes):
24+
pass
25+
26+
27+
DefragResult._encoded_counterpart = DefragResultBytes
28+
DefragResultBytes._decoded_counterpart = DefragResult
29+
30+
# Due to differences in type and native subclass printing,
31+
# the best thing we can do here is to just test that no exceptions
32+
# happen
33+
34+
#print(DefragResult, DefragResult._encoded_counterpart)
35+
#print(DefragResultBytes, DefragResultBytes._decoded_counterpart)
36+
37+
o1 = DefragResult("a", "b")
38+
#print(o1, type(o1))
39+
o2 = DefragResultBytes("a", "b")
40+
#print(o2, type(o2))
41+
42+
#print(o1._encoded_counterpart)
43+
_o1 = o1.encode()
44+
print(_o1[0], _o1[1])
45+
#print(_o1, type(_o1))
46+
47+
print("All's ok")

tests/basics/int1.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
print(int('0100', 2))
4747
print(int(' \t 0o12', 8))
4848
print(int('0o12 \t ', 8))
49+
print(int(b"12", 10))
4950

5051

5152
def test(value, base):

0 commit comments

Comments
 (0)