Merge branch 'master' of github.com:micropython/micropython

Conflicts:
	py/objstr.c
	py/py.mk
	py/stream.c
	unix/main.c
	unix/socket.c
diff --git a/examples/unix/sock-client.py b/examples/unix/sock-client.py
index d5d5021..08a39b1 100644
--- a/examples/unix/sock-client.py
+++ b/examples/unix/sock-client.py
@@ -1,22 +1,32 @@
-mod = rawsocket
-s = mod.socket()
+try:
+    import rawsocket as _socket
+except:
+    import _socket
+
+
+s = _socket.socket()
 
 if 1:
-    ai = mod.getaddrinfo("google.com", 80)
+    ai = _socket.getaddrinfo("google.com", 80)
     print("Address infos:", ai)
     addr = ai[0][4]
 else:
-    # Deprecated way to construct connection address
-    addr = mod.sockaddr_in()
+    # Deprecated ways to construct connection address
+    addr = _socket.sockaddr_in()
     addr.sin_family = 2
     #addr.sin_addr = (0x0100 << 16) + 0x007f
     #addr.sin_addr = (0x7f00 << 16) + 0x0001
-    #addr.sin_addr = mod.inet_aton("127.0.0.1")
-    addr.sin_addr = mod.gethostbyname("google.com")
-    addr.sin_port = mod.htons(80)
+    #addr.sin_addr = _socket.inet_aton("127.0.0.1")
+    addr.sin_addr = _socket.gethostbyname("google.com")
+    addr.sin_port = _socket.htons(80)
 
 print("Connect address:", addr)
 s.connect(addr)
 
-s.write("GET / HTTP/1.0\n\n")
-print(s.readall())
+if 0:
+    # MicroPython rawsocket module supports file interface directly
+    s.write("GET / HTTP/1.0\n\n")
+    print(s.readall())
+else:
+    s.send(b"GET / HTTP/1.0\n\n")
+    print(s.recv(4096))
diff --git a/examples/unix/sock-server.py b/examples/unix/sock-server.py
index c39a0af..ed14b7f 100644
--- a/examples/unix/sock-server.py
+++ b/examples/unix/sock-server.py
@@ -1,7 +1,18 @@
-mod = rawsocket
-s = mod.socket()
+try:
+    import rawsocket as socket
+except:
+    import socket
 
-ai = mod.getaddrinfo("127.0.0.1", 8080)
+
+CONTENT = """\
+HTTP/1.0 200 OK
+
+Hello #{} from MicroPython!
+"""
+
+s = socket.socket()
+
+ai = socket.getaddrinfo("127.0.0.1", 8080)
 print("Bind address info:", ai)
 addr = ai[0][4]
 
@@ -17,12 +28,13 @@
     print("Client address:", client_addr)
     print("Client socket:", client_s)
     print("Request:")
-    print(client_s.read(4096))
-    #print(client_s.readall())
-    client_s.write("""\
-HTTP/1.0 200 OK
-
-Hello #{} from MicroPython!
-""".format(counter))
+    if 0:
+        # MicroPython rawsocket module supports file interface directly
+        print(client_s.read(4096))
+        #print(client_s.readall())
+        client_s.write(CONTENT.format(counter))
+    else:
+        print(client_s.recv(4096))
+        client_s.send(bytes(CONTENT.format(counter), "ascii"))
     client_s.close()
     counter += 1
diff --git a/py/builtin.c b/py/builtin.c
index 8340ad3..9cbc037 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -350,3 +350,15 @@
 }
 
 MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_str_obj, mp_builtin_str);
+
+// TODO: This should be type, this is just quick CPython compat hack
+static mp_obj_t mp_builtin_bytes(uint n_args, const mp_obj_t *args) {
+    if (!MP_OBJ_IS_QSTR(args[0]) && !MP_OBJ_IS_TYPE(args[0], &str_type)) {
+        assert(0);
+    }
+    // Currently, MicroPython strings are mix between CPython byte and unicode
+    // strings. So, conversion is null so far.
+    return args[0];
+}
+
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_bytes_obj, 1, 3, mp_builtin_bytes);
diff --git a/py/builtin.h b/py/builtin.h
index 050a216..4257de5 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -5,6 +5,7 @@
 MP_DECLARE_CONST_FUN_OBJ(mp_builtin_abs_obj);
 MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj);
 MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_builtin_bytes_obj); // Temporary hack
 MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj);
 MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj);
 MP_DECLARE_CONST_FUN_OBJ(mp_builtin_divmod_obj);
diff --git a/py/obj.c b/py/obj.c
index 5a6c083..8a073f4 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -28,6 +28,8 @@
 const char *mp_obj_get_type_str(mp_obj_t o_in) {
     if (MP_OBJ_IS_SMALL_INT(o_in)) {
         return "int";
+    } else if (MP_OBJ_IS_QSTR(o_in)) {
+        return "str";
     } else {
         mp_obj_base_t *o = o_in;
         return o->type->name;
@@ -222,7 +224,9 @@
 #endif
 
 qstr mp_obj_get_qstr(mp_obj_t arg) {
-    if (MP_OBJ_IS_TYPE(arg, &str_type)) {
+    if (MP_OBJ_IS_QSTR(arg)) {
+        return MP_OBJ_QSTR_VALUE(arg);
+    } else if (MP_OBJ_IS_TYPE(arg, &str_type)) {
         return mp_obj_str_get(arg);
     } else {
         assert(0);
@@ -286,3 +290,9 @@
     }
     return MP_OBJ_NEW_SMALL_INT(len);
 }
+
+// Return input argument. Useful as .getiter for objects which are
+// their own iterators, etc.
+mp_obj_t mp_identity(mp_obj_t self) {
+    return self;
+}
diff --git a/py/obj.h b/py/obj.h
index faf0231..c2ce325 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -351,6 +351,8 @@
 extern const mp_obj_type_t fun_bc_type;
 void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte **code);
 
+mp_obj_t mp_identity(mp_obj_t self);
+
 // generator
 extern const mp_obj_type_t gen_instance_type;
 
@@ -374,3 +376,6 @@
     mp_obj_base_t base;
     mp_obj_t fun;
 } mp_obj_classmethod_t;
+
+// sequence helpers
+void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest);
diff --git a/py/objlist.c b/py/objlist.c
index bc363d3..2e9a870 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -153,13 +153,8 @@
                 return NULL;
             }
             int n = MP_OBJ_SMALL_INT_VALUE(rhs);
-            int len = o->len;
-            mp_obj_list_t *s = list_new(len * n);
-            mp_obj_t *dest = s->items;
-            for (int i = 0; i < n; i++) {
-                memcpy(dest, o->items, sizeof(mp_obj_t) * len);
-                dest += len;
-            }
+            mp_obj_list_t *s = list_new(o->len * n);
+            mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
             return s;
         }
         case RT_COMPARE_OP_EQUAL:
diff --git a/py/objstr.c b/py/objstr.c
index 3552058..f4dc857 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -65,9 +65,8 @@
             // TODO: need predicate to check for int-like type (bools are such for example)
             // ["no", "yes"][1 == 2] is common idiom
             if (MP_OBJ_IS_SMALL_INT(rhs_in)) {
-                // TODO: This implements byte string access for single index so far
-                // TODO: Handle negative indexes.
-                return mp_obj_new_int(lhs_data[mp_obj_get_int(rhs_in)]);
+                uint index = mp_get_index(lhs->base.type, lhs_len, rhs_in);
+                return mp_obj_new_str(qstr_from_strn((const char*)lhs_data + index, 1));
 #if MICROPY_ENABLE_SLICE
             } else if (MP_OBJ_IS_TYPE(rhs_in, &slice_type)) {
                 machine_int_t start, stop, step;
@@ -122,6 +121,16 @@
                 return mp_const_false;
             }
             break;
+        case RT_BINARY_OP_MULTIPLY:
+        {
+            if (!MP_OBJ_IS_SMALL_INT(rhs_in)) {
+                return NULL;
+            }
+            int n = MP_OBJ_SMALL_INT_VALUE(rhs_in);
+            char *s = m_new(char, lhs_len * n);
+            mp_seq_multiply(lhs_data, sizeof(*lhs_data), lhs_len, n, s);
+            return MP_OBJ_NEW_QSTR(qstr_from_strn_take(s, lhs_len * n, lhs_len * n));
+        }
     }
 
     return MP_OBJ_NULL; // op not supported
@@ -184,6 +193,45 @@
     nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's"));
 }
 
+#define is_ws(c) ((c) == ' ' || (c) == '\t')
+
+static mp_obj_t str_split(uint n_args, const mp_obj_t *args) {
+    int splits = -1;
+    mp_obj_t sep = mp_const_none;
+    if (n_args > 1) {
+        sep = args[1];
+        if (n_args > 2) {
+            splits = MP_OBJ_SMALL_INT_VALUE(args[2]);
+        }
+    }
+    assert(sep == mp_const_none);
+    (void)sep; // unused; to hush compiler warning
+    mp_obj_t res = mp_obj_new_list(0, NULL);
+    const char *s = qstr_str(mp_obj_str_get(args[0]));
+    const char *start;
+
+    // Initial whitespace is not counted as split, so we pre-do it
+    while (is_ws(*s)) s++;
+    while (*s && splits != 0) {
+        start = s;
+        while (*s != 0 && !is_ws(*s)) s++;
+        rt_list_append(res, MP_OBJ_NEW_QSTR(qstr_from_strn(start, s - start)));
+        if (*s == 0) {
+            break;
+        }
+        while (is_ws(*s)) s++;
+        if (splits > 0) {
+            splits--;
+        }
+    }
+
+    if (*s != 0) {
+        rt_list_append(res, MP_OBJ_NEW_QSTR(qstr_from_str(s)));
+    }
+
+    return res;
+}
+
 static bool chr_in_str(const char* const str, const size_t str_len, const char c) {
     for (size_t i = 0; i < str_len; i++) {
         if (str[i] == c) {
@@ -195,16 +243,8 @@
 
 static mp_obj_t str_find(uint n_args, const mp_obj_t *args) {
     assert(2 <= n_args && n_args <= 4);
-    assert(MP_OBJ_IS_TYPE(args[0], &str_type));
-    if (!MP_OBJ_IS_TYPE(args[1], &str_type)) {
-        nlr_jump(mp_obj_new_exception_msg_1_arg(
-                     MP_QSTR_TypeError,
-                     "Can't convert '%s' object to str implicitly",
-                     mp_obj_get_type_str(args[1])));
-    }
-
-    const char* haystack = qstr_str(((mp_obj_str_t*)args[0])->qstr);
-    const char* needle = qstr_str(((mp_obj_str_t*)args[1])->qstr);
+    const char* haystack = qstr_str(mp_obj_str_get(args[0]));
+    const char* needle = qstr_str(mp_obj_str_get(args[1]));
 
     size_t haystack_len = strlen(haystack);
     size_t needle_len = strlen(needle);
@@ -242,14 +282,11 @@
     if (n_args == 1) {
         chars_to_del = whitespace;
     } else {
-        assert(MP_OBJ_IS_TYPE(args[1], &str_type));
-        mp_obj_str_t *chars_to_del_obj = args[1];
-        chars_to_del = qstr_str(chars_to_del_obj->qstr);
+        chars_to_del = qstr_str(mp_obj_str_get(args[1]));
     }
 
     const size_t chars_to_del_len = strlen(chars_to_del);
-    mp_obj_str_t *self = args[0];
-    const char *orig_str = qstr_str(self->qstr);
+    const char *orig_str = qstr_str(mp_obj_str_get(args[0]));
     const size_t orig_str_len = strlen(orig_str);
 
     size_t first_good_char_pos = 0;
@@ -307,12 +344,14 @@
 
 static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
 static MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
+static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split);
 static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);
 static MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, str_format);
 
 static const mp_method_t str_type_methods[] = {
     { "find", &str_find_obj },
     { "join", &str_join_obj },
+    { "split", &str_split_obj },
     { "strip", &str_strip_obj },
     { "format", &str_format_obj },
     { NULL, NULL }, // end-of-list sentinel
@@ -335,9 +374,15 @@
 }
 
 qstr mp_obj_str_get(mp_obj_t self_in) {
-    assert(MP_OBJ_IS_TYPE(self_in, &str_type));
-    mp_obj_str_t *self = self_in;
-    return self->qstr;
+    if (MP_OBJ_IS_QSTR(self_in)) {
+        return MP_OBJ_QSTR_VALUE(self_in);
+    }
+    if (MP_OBJ_IS_TYPE(self_in, &str_type)) {
+        mp_obj_str_t *self = self_in;
+        return self->qstr;
+    }
+    nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "Can't convert '%s' object to str implicitly",
+             mp_obj_get_type_str(self_in)));
 }
 
 /******************************************************************************/
diff --git a/py/py.mk b/py/py.mk
index 72013ef..75394b3 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -97,6 +97,7 @@
 	objtuple.o \
 	objtype.o \
 	objzip.o \
+	sequence.o \
 	stream.o \
 	builtin.o \
 	builtinimport.o \
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 10b1fc0..9bc01c5 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -40,6 +40,7 @@
 Q(array)
 Q(bool)
 Q(bytearray)
+Q(bytes)
 Q(callable)
 Q(chr)
 Q(complex)
diff --git a/py/runtime.c b/py/runtime.c
index 210047a..ccd3d7d 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -130,6 +130,7 @@
     mp_map_add_qstr(&map_builtins, MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj);
     mp_map_add_qstr(&map_builtins, MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj);
     mp_map_add_qstr(&map_builtins, MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj);
+    mp_map_add_qstr(&map_builtins, MP_QSTR_bytes, (mp_obj_t)&mp_builtin_bytes_obj);
     mp_map_add_qstr(&map_builtins, MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj);
     mp_map_add_qstr(&map_builtins, MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj);
     mp_map_add_qstr(&map_builtins, MP_QSTR_divmod, (mp_obj_t)&mp_builtin_divmod_obj);
diff --git a/py/sequence.c b/py/sequence.c
new file mode 100644
index 0000000..56718c6
--- /dev/null
+++ b/py/sequence.c
@@ -0,0 +1,25 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "map.h"
+#include "runtime0.h"
+#include "runtime.h"
+
+// Helpers for sequence types
+
+// Implements backend of sequence * integer operation. Assumes elements are
+// memory-adjacent in sequence.
+void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest) {
+    for (int i = 0; i < times; i++) {
+        uint copy_sz = item_sz * len;
+        memcpy(dest, items, copy_sz);
+        dest = (char*)dest + copy_sz;
+    }
+}
diff --git a/py/stream.c b/py/stream.c
index 88ddc5e..be560d3 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -30,7 +30,8 @@
         nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error));
     } else {
         // TODO don't intern this string
-        return mp_obj_new_str(qstr_from_strn_take(buf, sz, out_sz));
+        buf = m_realloc(buf, sz, out_sz);
+        return mp_obj_new_str(qstr_from_strn_take(buf, out_sz, out_sz));
     }
 }
 
@@ -134,9 +135,18 @@
     }
     // TODO don't intern this string
     vstr_shrink(vstr);
-    return mp_obj_new_str(qstr_from_strn_take(vstr_str(vstr), vstr->alloc, vstr_len(vstr)));
+    return MP_OBJ_NEW_QSTR(qstr_from_strn_take(vstr_str(vstr), vstr->alloc, vstr_len(vstr)));
 }
 
+mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
+    mp_obj_t l_in = stream_unbuffered_readline(1, &self);
+    const char *l = qstr_str(MP_OBJ_QSTR_VALUE(l_in));
+    // TODO: \0
+    if (*l != 0) {
+        return l_in;
+    }
+    return mp_const_stop_iteration;
+}
 
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read);
 MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall);
diff --git a/py/stream.h b/py/stream.h
index 58e8072..a0cc347 100644
--- a/py/stream.h
+++ b/py/stream.h
@@ -2,3 +2,6 @@
 extern const mp_obj_fun_native_t mp_stream_readall_obj;
 extern const mp_obj_fun_native_t mp_stream_unbuffered_readline_obj;
 extern const mp_obj_fun_native_t mp_stream_write_obj;
+
+// Iterator which uses mp_stream_unbuffered_readline_obj
+mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self);
diff --git a/tests/basics/string1.py b/tests/basics/string1.py
index 3fecf79..074b04e 100644
--- a/tests/basics/string1.py
+++ b/tests/basics/string1.py
@@ -8,6 +8,19 @@
 
 print('123' + "456")
 
+print('123' * 5)
+
+print('abc'[1])
+print('abc'[-1])
+try:
+    'abc'[100]
+except IndexError:
+    print('caught')
+try:
+    'abc'[-4]
+except IndexError:
+    print('caught2')
+
 # iter
 print(list('str'))
 
diff --git a/tests/basics/string_split.py b/tests/basics/string_split.py
new file mode 100644
index 0000000..f73cb42
--- /dev/null
+++ b/tests/basics/string_split.py
@@ -0,0 +1,7 @@
+print("a b".split())
+print("   a   b    ".split(None))
+print("   a   b    ".split(None, 1))
+print("   a   b    ".split(None, 2))
+print("   a   b  c  ".split(None, 1))
+print("   a   b  c  ".split(None, 0))
+print("   a   b  c  ".split(None, -1))
diff --git a/tests/io/file-iter.py b/tests/io/file-iter.py
new file mode 100644
index 0000000..48e8739
--- /dev/null
+++ b/tests/io/file-iter.py
@@ -0,0 +1,3 @@
+f = open("io/data/file1")
+for l in f:
+    print(l)
diff --git a/tests/run-tests b/tests/run-tests
index ef13687..752138c 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -10,7 +10,14 @@
 numfailed=0
 namefailed=
 
-for infile in basics/*.py io/*.py
+if [ $# -eq 0 ]
+then
+    tests="basics/*.py io/*.py"
+else
+    tests="$@"
+fi
+
+for infile in $tests
 do
     basename=`basename $infile .py`
     outfile=${basename}.out
diff --git a/unix/file.c b/unix/file.c
index 72c56ca..3181c08 100644
--- a/unix/file.c
+++ b/unix/file.c
@@ -8,6 +8,7 @@
 #include "mpconfig.h"
 #include "qstr.h"
 #include "obj.h"
+#include "runtime.h"
 #include "stream.h"
 
 typedef struct _mp_obj_fdfile_t {
@@ -15,6 +16,8 @@
     int fd;
 } mp_obj_fdfile_t;
 
+static const mp_obj_type_t rawfile_type;
+
 static void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
     mp_obj_fdfile_t *self = self_in;
     print(env, "<io.FileIO %d>", self->fd);
@@ -45,6 +48,13 @@
 }
 static MP_DEFINE_CONST_FUN_OBJ_1(fdfile_close_obj, fdfile_close);
 
+static mp_obj_fdfile_t *fdfile_new(int fd) {
+    mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
+    o->base.type = &rawfile_type;
+    o->fd = fd;
+    return o;
+}
+
 static mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
     mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
     o->base.type = type_in;
@@ -81,11 +91,11 @@
         }
     }
 
-    o->fd = open(fname, mode, 0644);
-    if (o->fd == -1) {
-        nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_OSError, "[Errno %d]", (const char *)(machine_int_t)errno));
+    int fd = open(fname, mode, 0644);
+    if (fd == -1) {
+        nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", errno));
     }
-    return o;
+    return fdfile_new(fd);
 }
 
 static const mp_method_t rawfile_type_methods[] = {
@@ -102,8 +112,8 @@
     "io.FileIO",
     .print = fdfile_print,
     .make_new = fdfile_make_new,
-    .getiter = NULL,
-    .iternext = NULL,
+    .getiter = mp_identity,
+    .iternext = mp_stream_unbuffered_iter,
     .stream_p = {
         .read = fdfile_read,
         .write = fdfile_write,
@@ -117,3 +127,12 @@
     return fdfile_make_new((mp_obj_t)&rawfile_type, n_args, 0, args);
 }
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open);
+
+void file_init() {
+    rt_store_name(MP_QSTR_open, (mp_obj_t)&mp_builtin_open_obj);
+
+    mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys);
+    rt_store_attr(m_sys, MP_QSTR_stdin, fdfile_new(STDIN_FILENO));
+    rt_store_attr(m_sys, MP_QSTR_stdout, fdfile_new(STDOUT_FILENO));
+    rt_store_attr(m_sys, MP_QSTR_stderr, fdfile_new(STDERR_FILENO));
+}
diff --git a/unix/main.c b/unix/main.c
index 74e903c..facc250 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -22,6 +22,7 @@
 #endif
 
 extern const mp_obj_fun_native_t mp_builtin_open_obj;
+void file_init();
 void rawsocket_init();
 
 static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
@@ -222,7 +223,8 @@
     rt_store_attr(m_sys, MP_QSTR_argv, py_argv);
 
     rt_store_name(qstr_from_str("test"), test_obj_new(42));
-    rt_store_name(MP_QSTR_open, (mp_obj_t)&mp_builtin_open_obj);
+
+    file_init();
     rawsocket_init();
 
     // Here is some example code to create a class and instance of that class.
diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h
index 3178f0a..a470e5d 100644
--- a/unix/qstrdefsport.h
+++ b/unix/qstrdefsport.h
@@ -3,6 +3,9 @@
 Q(sys)
 Q(argv)
 Q(open)
+Q(stdin)
+Q(stdout)
+Q(stderr)
 Q(rawsocket)
 Q(socket)
 Q(sockaddr_in)
diff --git a/unix/socket.c b/unix/socket.c
index e43695c..ae87ba4 100644
--- a/unix/socket.c
+++ b/unix/socket.c
@@ -127,6 +127,41 @@
 }
 static MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
 
+static mp_obj_t socket_recv(uint n_args, const mp_obj_t *args) {
+    mp_obj_socket_t *self = args[0];
+    int sz = MP_OBJ_SMALL_INT_VALUE(args[1]);
+    int flags = 0;
+
+    if (n_args > 2) {
+        flags = MP_OBJ_SMALL_INT_VALUE(args[2]);
+    }
+
+    char *buf = m_new(char, sz);
+    int out_sz = recv(self->fd, buf, sz, flags);
+    RAISE_ERRNO(out_sz, errno);
+
+    buf = m_realloc(buf, sz, out_sz);
+    return MP_OBJ_NEW_QSTR(qstr_from_strn_take(buf, out_sz, out_sz));
+}
+static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_obj, 2, 3, socket_recv);
+
+static mp_obj_t socket_send(uint n_args, const mp_obj_t *args) {
+    mp_obj_socket_t *self = args[0];
+    int flags = 0;
+
+    if (n_args > 2) {
+        flags = MP_OBJ_SMALL_INT_VALUE(args[2]);
+    }
+
+    const char *buf = qstr_str(mp_obj_str_get(args[1]));
+    int sz = strlen(buf);
+    int out_sz = send(self->fd, buf, sz, flags);
+    RAISE_ERRNO(out_sz, errno);
+
+    return MP_OBJ_NEW_SMALL_INT((machine_int_t)out_sz);
+}
+static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_send_obj, 2, 3, socket_send);
+
 static mp_obj_t socket_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
     int family = AF_INET;
     int type = SOCK_STREAM;
@@ -159,6 +194,8 @@
         { "bind", &socket_bind_obj },
         { "listen", &socket_listen_obj },
         { "accept", &socket_accept_obj },
+        { "recv", &socket_recv_obj },
+        { "send", &socket_send_obj },
         { "close", &socket_close_obj },
 #if MICROPY_SOCKET_EXTRA
         { "recv", &mp_stream_read_obj },
@@ -280,5 +317,4 @@
     STORE_INT_CONST(m, SOCK_STREAM);
     STORE_INT_CONST(m, SOCK_DGRAM);
     STORE_INT_CONST(m, SOCK_RAW);
-    rt_store_name(MP_QSTR_rawsocket, m);
 }