STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { // Currently supports only blocking mode (void)self_in; if (!mp_obj_is_true(flag_in)) { mp_not_implemented(""); } return mp_const_none; }
STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_jobject_t *self = self_in; mp_uint_t idx = mp_obj_get_int(index); char class_name[64]; get_jclass_name(self->obj, class_name); //printf("class: %s\n", class_name); if (class_name[0] == '[') { if (class_name[1] == 'L' || class_name[1] == '[') { if (value == MP_OBJ_NULL) { // delete assert(0); } else if (value == MP_OBJ_SENTINEL) { // load jobject el = JJ(GetObjectArrayElement, self->obj, idx); return new_jobject(el); } else { // store jvalue jval; const char *t = class_name + 1; py2jvalue(&t, value, &jval); JJ(SetObjectArrayElement, self->obj, idx, jval.l); return mp_const_none; } } mp_not_implemented(""); } if (!JJ(IsInstanceOf, self->obj, List_class)) { return MP_OBJ_NULL; } if (value == MP_OBJ_NULL) { // delete assert(0); } else if (value == MP_OBJ_SENTINEL) { // load jobject el = JJ(CallObjectMethod, self->obj, List_get_mid, idx); check_exception(); return new_jobject(el); } else { // store assert(0); } return MP_OBJ_NULL; }
/** * Remove given empty directory path. * * def rmdir(path) */ static mp_obj_t os_rmdir(mp_obj_t path_in) { const char *path_p; int res; path_p = mp_obj_str_get_str(path_in); res = -1; mp_not_implemented("os_rmdir()"); if (res != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing directory '%s'", path_p)); } return (mp_const_none); }
STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(self_in); assert(type == &mp_type_str); GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { // load #if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_obj_t ostart, ostop, ostep; mp_obj_slice_get(index, &ostart, &ostop, &ostep); if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { mp_not_implemented("only slices with step=1 (aka None) are supported"); } const byte *pstart, *pstop; if (ostart != mp_const_none) { pstart = str_index_to_ptr(type, self_data, self_len, ostart, true); } else { pstart = self_data; } if (ostop != mp_const_none) { // pstop will point just after the stop character. This depends on // the \0 at the end of the string. pstop = str_index_to_ptr(type, self_data, self_len, ostop, true); } else { pstop = self_data + self_len; } if (pstop < pstart) { return MP_OBJ_NEW_QSTR(MP_QSTR_); } return mp_obj_new_str_of_type(type, (const byte *)pstart, pstop - pstart); } #endif const byte *s = str_index_to_ptr(type, self_data, self_len, index, false); int len = 1; if (UTF8_IS_NONASCII(*s)) { // Count the number of 1 bits (after the first) for (char mask = 0x40; *s & mask; mask >>= 1) { ++len; } } return mp_obj_new_str((const char*)s, len, true); // This will create a one-character string } else { return MP_OBJ_NULL; // op not supported
/** * Remove given empty directory. * * def rename(src, dst) */ static mp_obj_t os_rename(mp_obj_t path_src_in, mp_obj_t path_dst_in) { const char *src_path_p; const char *dst_path_p; int res; src_path_p = mp_obj_str_get_str(path_src_in); dst_path_p = mp_obj_str_get_str(path_dst_in); res = -1; mp_not_implemented("os_rename()"); if (res != 0) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error renaming file '%s' to '%s'", src_path_p, dst_path_p)); } return (mp_const_none); }
STATIC mp_obj_t re_split(mp_uint_t n_args, const mp_obj_t *args) { mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]); Subject subj; mp_uint_t len; subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; int caps_num = (self->re.sub + 1) * 2; int maxsplit = 0; if (n_args > 2) { maxsplit = mp_obj_get_int(args[2]); } mp_obj_t retval = mp_obj_new_list(0, NULL); const char **caps = alloca(caps_num * sizeof(char*)); while (true) { // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char memset((char**)caps, 0, caps_num * sizeof(char*)); int res = re1_5_recursiveloopprog(&self->re, &subj, caps, caps_num, false); // if we didn't have a match, or had an empty match, it's time to stop if (!res || caps[0] == caps[1]) { break; } mp_obj_t s = mp_obj_new_str(subj.begin, caps[0] - subj.begin, false); mp_obj_list_append(retval, s); if (self->re.sub > 0) { mp_not_implemented("Splitting with sub-captures"); } subj.begin = caps[1]; if (maxsplit > 0 && --maxsplit == 0) { break; } } mp_obj_t s = mp_obj_new_str(subj.begin, subj.end - subj.begin, false); mp_obj_list_append(retval, s); return retval; }
STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) { lwip_socket_obj_t *socket = self_in; lwip_socket_check_connected(socket); int _errno; mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); mp_uint_t ret = 0; switch (socket->type) { case MOD_NETWORK_SOCK_STREAM: { if (socket->timeout == 0) { // Behavior of sendall() for non-blocking sockets isn't explicitly specified. // But it's specified that "On error, an exception is raised, there is no // way to determine how much data, if any, was successfully sent." Then, the // most useful behavior is: check whether we will be able to send all of input // data without EAGAIN, and if won't be, raise it without sending any. if (bufinfo.len > tcp_sndbuf(socket->pcb.tcp)) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EAGAIN))); } } // TODO: In CPython3.5, socket timeout should apply to the // entire sendall() operation, not to individual send() chunks. while (bufinfo.len != 0) { ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno); if (ret == -1) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } bufinfo.len -= ret; bufinfo.buf = (char*)bufinfo.buf + ret; } break; } case MOD_NETWORK_SOCK_DGRAM: mp_not_implemented(""); break; } return mp_const_none; }
STATIC mp_obj_t re_split(uint n_args, const mp_obj_t *args) { mp_obj_re_t *self = args[0]; Subject subj; mp_uint_t len; subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; int caps_num = (self->re.sub + 1) * 2; int maxsplit = 0; if (n_args > 2) { maxsplit = mp_obj_int_get_truncated(args[2]); } mp_obj_t retval = mp_obj_new_list(0, NULL); const char **caps = alloca(caps_num * sizeof(char*)); while (true) { int res = re1_5_recursiveloopprog(&self->re, &subj, caps, caps_num, false); // if we didn't have a match, or had an empty match, it's time to stop if (!res || caps[0] == caps[1]) { break; } mp_obj_t s = mp_obj_new_str(subj.begin, caps[0] - subj.begin, false); mp_obj_list_append(retval, s); if (self->re.sub > 0) { mp_not_implemented("Splitting with sub-captures"); } subj.begin = caps[1]; if (maxsplit > 0 && --maxsplit == 0) { break; } } mp_obj_t s = mp_obj_new_str(subj.begin, subj.end - subj.begin, false); mp_obj_list_append(retval, s); return retval; }
STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0]; if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) { // CPython: io.UnsupportedOperation, OSError subclass nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported")); } mp_int_t sz; if (n_args == 1 || ((sz = mp_obj_get_int(args[1])) == -1)) { return stream_readall(args[0]); } #if MICROPY_PY_BUILTINS_STR_UNICODE if (!o->type->stream_p->is_bytes) { mp_not_implemented("Reading from unicode text streams by character count"); } #endif byte *buf = m_new(byte, sz); int error; mp_int_t out_sz = o->type->stream_p->read(o, buf, sz, &error); if (out_sz == -1) { if (is_nonblocking_error(error)) { // https://docs.python.org/3.4/library/io.html#io.RawIOBase.read // "If the object is in non-blocking mode and no bytes are available, // None is returned." // This is actually very weird, as naive truth check will treat // this as EOF. return mp_const_none; } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error)); } else { mp_obj_t s = mp_obj_new_str_of_type(STREAM_CONTENT_TYPE(o->type->stream_p), buf, out_sz); // will reallocate to use exact size m_free(buf, sz); return s; } }
static mp_obj_t module_thrd_set_name(mp_obj_t name_in) { mp_not_implemented("thrd_set_name"); return (mp_const_none); }
static mp_obj_t module_thrd_join(mp_obj_t thrd_in) { mp_not_implemented("thrd_join"); return (mp_const_none); }
static mp_obj_t module_thrd_set_env(mp_obj_t name_in, mp_obj_t value_in) { mp_not_implemented("thrd_set_env"); return (mp_const_none); }
STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item // TODO implement // TODO: confirmed that both bytearray and array.array support // slice deletion return MP_OBJ_NULL; // op not supported } else { mp_obj_array_t *o = self_in; if (0) { #if MICROPY_PY_BUILTINS_SLICE } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) { mp_not_implemented("only slices with step=1 (aka None) are supported"); } if (value != MP_OBJ_SENTINEL) { #if MICROPY_PY_ARRAY_SLICE_ASSIGN // Assign mp_uint_t src_len; void *src_items; size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); if (MP_OBJ_IS_OBJ(value) && ((mp_obj_base_t*)value)->type->subscr == array_subscr) { // value is array, bytearray or memoryview mp_obj_array_t *src_slice = value; if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) { compat_error: nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "lhs and rhs should be compatible")); } src_len = src_slice->len; src_items = src_slice->items; #if MICROPY_PY_BUILTINS_MEMORYVIEW if (MP_OBJ_IS_TYPE(value, &mp_type_memoryview)) { src_items = (uint8_t*)src_items + (src_slice->free * item_sz); } #endif } else if (MP_OBJ_IS_TYPE(value, &mp_type_bytes)) { if (item_sz != 1) { goto compat_error; } mp_buffer_info_t bufinfo; mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_READ); src_len = bufinfo.len; src_items = bufinfo.buf; } else { mp_not_implemented("array/bytes required on right side"); } // TODO: check src/dst compat mp_int_t len_adj = src_len - (slice.stop - slice.start); uint8_t* dest_items = o->items; #if MICROPY_PY_BUILTINS_MEMORYVIEW if (o->base.type == &mp_type_memoryview) { if (len_adj != 0) { goto compat_error; } dest_items += o->free * item_sz; } #endif if (len_adj > 0) { if (len_adj > o->free) { // TODO: alloc policy; at the moment we go conservative o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz); o->free = 0; } mp_seq_replace_slice_grow_inplace(dest_items, o->len, slice.start, slice.stop, src_items, src_len, len_adj, item_sz); } else { mp_seq_replace_slice_no_grow(dest_items, o->len, slice.start, slice.stop, src_items, src_len, item_sz); // Clear "freed" elements at the end of list // TODO: This is actually only needed for typecode=='O' mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz); // TODO: alloc policy after shrinking } o->len += len_adj; return mp_const_none; #else return MP_OBJ_NULL; // op not supported #endif } mp_obj_array_t *res; size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); assert(sz > 0); if (0) { // dummy #if MICROPY_PY_BUILTINS_MEMORYVIEW } else if (o->base.type == &mp_type_memoryview) { res = m_new_obj(mp_obj_array_t); *res = *o; res->free += slice.start; res->len = slice.stop - slice.start; #endif } else { res = array_new(o->typecode, slice.stop - slice.start); memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz); } return res; #endif } else { mp_uint_t index = mp_get_index(o->base.type, o->len, index_in, false); #if MICROPY_PY_BUILTINS_MEMORYVIEW if (o->base.type == &mp_type_memoryview) { index += o->free; if (value != MP_OBJ_SENTINEL && (o->typecode & 0x80) == 0) { // store to read-only memoryview return MP_OBJ_NULL; } } #endif if (value == MP_OBJ_SENTINEL) { // load return mp_binary_get_val_array(o->typecode & TYPECODE_MASK, o->items, index); } else { // store mp_binary_set_val_array(o->typecode & TYPECODE_MASK, o->items, index, value); return mp_const_none; } } } }
STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw) { // get first quoting character char quote_char = '\''; if (is_char(lex, '\"')) { quote_char = '\"'; } next_char(lex); // work out if it's a single or triple quoted literal size_t num_quotes; if (is_char_and(lex, quote_char, quote_char)) { // triple quotes next_char(lex); next_char(lex); num_quotes = 3; } else { // single quotes num_quotes = 1; } size_t n_closing = 0; while (!is_end(lex) && (num_quotes > 1 || !is_char(lex, '\n')) && n_closing < num_quotes) { if (is_char(lex, quote_char)) { n_closing += 1; vstr_add_char(&lex->vstr, CUR_CHAR(lex)); } else { n_closing = 0; if (is_char(lex, '\\')) { next_char(lex); unichar c = CUR_CHAR(lex); if (is_raw) { // raw strings allow escaping of quotes, but the backslash is also emitted vstr_add_char(&lex->vstr, '\\'); } else { switch (c) { // note: "c" can never be MP_LEXER_EOF because next_char // always inserts a newline at the end of the input stream case '\n': c = MP_LEXER_EOF; break; // backslash escape the newline, just ignore it case '\\': break; case '\'': break; case '"': break; case 'a': c = 0x07; break; case 'b': c = 0x08; break; case 't': c = 0x09; break; case 'n': c = 0x0a; break; case 'v': c = 0x0b; break; case 'f': c = 0x0c; break; case 'r': c = 0x0d; break; case 'u': case 'U': if (lex->tok_kind == MP_TOKEN_BYTES) { // b'\u1234' == b'\\u1234' vstr_add_char(&lex->vstr, '\\'); break; } // Otherwise fall through. case 'x': { mp_uint_t num = 0; if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) { // not enough hex chars for escape sequence lex->tok_kind = MP_TOKEN_INVALID; } c = num; break; } case 'N': // Supporting '\N{LATIN SMALL LETTER A}' == 'a' would require keeping the // entire Unicode name table in the core. As of Unicode 6.3.0, that's nearly // 3MB of text; even gzip-compressed and with minimal structure, it'll take // roughly half a meg of storage. This form of Unicode escape may be added // later on, but it's definitely not a priority right now. -- CJA 20140607 mp_not_implemented("unicode name escapes"); break; default: if (c >= '0' && c <= '7') { // Octal sequence, 1-3 chars size_t digits = 3; mp_uint_t num = c - '0'; while (is_following_odigit(lex) && --digits != 0) { next_char(lex); num = num * 8 + (CUR_CHAR(lex) - '0'); } c = num; } else { // unrecognised escape character; CPython lets this through verbatim as '\' and then the character vstr_add_char(&lex->vstr, '\\'); } break; } } if (c != MP_LEXER_EOF) { if (MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) { if (c < 0x110000 && lex->tok_kind == MP_TOKEN_STRING) { vstr_add_char(&lex->vstr, c); } else if (c < 0x100 && lex->tok_kind == MP_TOKEN_BYTES) { vstr_add_byte(&lex->vstr, c); } else { // unicode character out of range // this raises a generic SyntaxError; could provide more info lex->tok_kind = MP_TOKEN_INVALID; } } else { // without unicode everything is just added as an 8-bit byte if (c < 0x100) { vstr_add_byte(&lex->vstr, c); } else { // 8-bit character out of range // this raises a generic SyntaxError; could provide more info lex->tok_kind = MP_TOKEN_INVALID; } } } } else { // Add the "character" as a byte so that we remain 8-bit clean. // This way, strings are parsed correctly whether or not they contain utf-8 chars. vstr_add_byte(&lex->vstr, CUR_CHAR(lex)); } } next_char(lex); } // check we got the required end quotes if (n_closing < num_quotes) { lex->tok_kind = MP_TOKEN_LONELY_STRING_OPEN; } // cut off the end quotes from the token text vstr_cut_tail_bytes(&lex->vstr, n_closing); }
STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete #if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { mp_not_implemented(""); } mp_int_t len_adj = slice.start - slice.stop; //printf("Len adj: %d\n", len_adj); assert(len_adj <= 0); mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items/*NULL*/, 0, sizeof(*self->items)); // Clear "freed" elements at the end of list mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); self->len += len_adj; return mp_const_none; } #endif mp_obj_t args[2] = {self_in, index}; list_pop(2, args); return mp_const_none; } else if (value == MP_OBJ_SENTINEL) { // load mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_bound_slice_t slice; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { return mp_seq_extract_slice(self->len, self->items, &slice); } mp_obj_list_t *res = list_new(slice.stop - slice.start); mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); return MP_OBJ_FROM_PTR(res); } #endif size_t index_val = mp_get_index(self->base.type, self->len, index, false); return self->items[index_val]; } else { #if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); size_t value_len; mp_obj_t *value_items; mp_obj_get_array(value, &value_len, &value_items); mp_bound_slice_t slice_out; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) { mp_not_implemented(""); } mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start); //printf("Len adj: %d\n", len_adj); if (len_adj > 0) { if (self->len + len_adj > self->alloc) { // TODO: Might optimize memory copies here by checking if block can // be grown inplace or not self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj); self->alloc = self->len + len_adj; } mp_seq_replace_slice_grow_inplace(self->items, self->len, slice_out.start, slice_out.stop, value_items, value_len, len_adj, sizeof(*self->items)); } else { mp_seq_replace_slice_no_grow(self->items, self->len, slice_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items)); // Clear "freed" elements at the end of list mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); // TODO: apply allocation policy re: alloc_size } self->len += len_adj; return mp_const_none; } #endif mp_obj_list_store(self_in, index, value); return mp_const_none; } }
NORETURN void mp_arg_error_unimpl_kw(void) { mp_not_implemented("keyword argument(s) not yet implemented - use normal args instead"); }