py: Implement proper separation between io.FileIO and io.TextIOWrapper.
io.FileIO is binary I/O, ans actually optional. Default file type is io.TextIOWrapper, which provides str results. CPython3 explicitly describes io.TextIOWrapper as buffered I/O, but we don't have buffering support yet anyway.
This commit is contained in:
parent
52386cafa0
commit
9e29666bf9
@ -32,11 +32,20 @@
|
||||
|
||||
#if MICROPY_ENABLE_MOD_IO
|
||||
|
||||
extern const mp_obj_type_t mp_type_fileio;
|
||||
extern const mp_obj_type_t mp_type_textio;
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_io_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_io) },
|
||||
// Note: mp_builtin_open_obj should be defined by port, it's not
|
||||
// part of the core.
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||
#if MICROPY_MOD_IO_FILEIO
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_FileIO), (mp_obj_t)&mp_type_fileio },
|
||||
#endif
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_TextIOWrapper), (mp_obj_t)&mp_type_textio },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_StringIO), (mp_obj_t)&mp_type_stringio },
|
||||
#if MICROPY_IO_BYTESIO
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BytesIO), (mp_obj_t)&mp_type_bytesio },
|
||||
|
@ -225,6 +225,10 @@ typedef double mp_float_t;
|
||||
#define MICROPY_ENABLE_MOD_IO (1)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_MOD_IO_FILEIO
|
||||
#define MICROPY_MOD_IO_FILEIO (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_IO_BYTESIO
|
||||
#define MICROPY_IO_BYTESIO (1)
|
||||
#endif
|
||||
|
@ -354,6 +354,8 @@ Q(io)
|
||||
Q(readall)
|
||||
Q(readline)
|
||||
Q(readlines)
|
||||
Q(FileIO)
|
||||
Q(TextIOWrapper)
|
||||
Q(StringIO)
|
||||
Q(BytesIO)
|
||||
Q(getvalue)
|
||||
|
@ -41,7 +41,7 @@ typedef struct _pyb_file_obj_t {
|
||||
} pyb_file_obj_t;
|
||||
|
||||
void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
printf("<io.FileIO %p>", self_in);
|
||||
printf("<io.%s %p>", mp_obj_get_type_str(self_in), self_in);
|
||||
}
|
||||
|
||||
STATIC machine_int_t file_read(mp_obj_t self_in, void *buf, machine_uint_t size, int *errcode) {
|
||||
@ -94,7 +94,7 @@ STATIC const mp_stream_p_t file_obj_stream_p = {
|
||||
.write = file_write,
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t file_obj_type = {
|
||||
const mp_obj_type_t mp_type_textio = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_FileIO,
|
||||
.make_new = file_obj_make_new,
|
||||
@ -113,7 +113,7 @@ STATIC mp_obj_t file_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, cons
|
||||
mode = mp_obj_str_get_str(args[1]);
|
||||
}
|
||||
pyb_file_obj_t *self = m_new_obj_with_finaliser(pyb_file_obj_t);
|
||||
self->base.type = &file_obj_type;
|
||||
self->base.type = &mp_type_textio;
|
||||
if (mode[0] == 'r') {
|
||||
// open for reading
|
||||
FRESULT res = f_open(&self->fp, filename, FA_READ);
|
||||
@ -138,7 +138,7 @@ STATIC mp_obj_t file_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, cons
|
||||
// Factory function for I/O stream classes
|
||||
STATIC mp_obj_t pyb_io_open(uint n_args, const mp_obj_t *args) {
|
||||
// TODO: analyze mode and buffering args and instantiate appropriate type
|
||||
return file_obj_make_new((mp_obj_t)&file_obj_type, n_args, 0, args);
|
||||
return file_obj_make_new((mp_obj_t)&mp_type_textio, n_args, 0, args);
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, pyb_io_open);
|
||||
|
73
unix/file.c
73
unix/file.c
@ -54,11 +54,12 @@ void check_fd_is_open(const mp_obj_fdfile_t *o) {
|
||||
#define check_fd_is_open(o)
|
||||
#endif
|
||||
|
||||
STATIC const mp_obj_type_t rawfile_type;
|
||||
extern const mp_obj_type_t mp_type_fileio;
|
||||
extern const mp_obj_type_t mp_type_textio;
|
||||
|
||||
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);
|
||||
print(env, "<io.%s %d>", mp_obj_get_type_str(self), self->fd);
|
||||
}
|
||||
|
||||
STATIC machine_int_t fdfile_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
|
||||
@ -103,23 +104,10 @@ STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno);
|
||||
|
||||
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;
|
||||
mp_const_obj_t type = type_in;
|
||||
|
||||
if (MP_OBJ_IS_SMALL_INT(args[0])) {
|
||||
o->fd = MP_OBJ_SMALL_INT_VALUE(args[0]);
|
||||
return o;
|
||||
}
|
||||
|
||||
const char *fname = mp_obj_str_get_str(args[0]);
|
||||
const char *mode_s;
|
||||
if (n_args > 1) {
|
||||
mode_s = mp_obj_str_get_str(args[1]);
|
||||
@ -143,14 +131,32 @@ STATIC mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
|
||||
case '+':
|
||||
mode |= O_RDWR;
|
||||
break;
|
||||
#if MICROPY_MOD_IO_FILEIO
|
||||
// If we don't have io.FileIO, then files are in text mode implicitly
|
||||
case 'b':
|
||||
type = &mp_type_fileio;
|
||||
break;
|
||||
case 't':
|
||||
type = &mp_type_textio;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
o->base.type = type;
|
||||
|
||||
if (MP_OBJ_IS_SMALL_INT(args[0])) {
|
||||
o->fd = MP_OBJ_SMALL_INT_VALUE(args[0]);
|
||||
return o;
|
||||
}
|
||||
|
||||
const char *fname = mp_obj_str_get_str(args[0]);
|
||||
int fd = open(fname, mode, 0644);
|
||||
if (fd == -1) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT((machine_int_t)errno)));
|
||||
}
|
||||
return fdfile_new(fd);
|
||||
o->fd = fd;
|
||||
return o;
|
||||
}
|
||||
|
||||
STATIC const mp_map_elem_t rawfile_locals_dict_table[] = {
|
||||
@ -167,29 +173,48 @@ STATIC const mp_map_elem_t rawfile_locals_dict_table[] = {
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
|
||||
|
||||
STATIC const mp_stream_p_t rawfile_stream_p = {
|
||||
#if MICROPY_MOD_IO_FILEIO
|
||||
STATIC const mp_stream_p_t fileio_stream_p = {
|
||||
.read = fdfile_read,
|
||||
.write = fdfile_write,
|
||||
.is_bytes = true,
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t rawfile_type = {
|
||||
const mp_obj_type_t mp_type_fileio = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_FileIO,
|
||||
.print = fdfile_print,
|
||||
.make_new = fdfile_make_new,
|
||||
.getiter = mp_identity,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.stream_p = &rawfile_stream_p,
|
||||
.stream_p = &fileio_stream_p,
|
||||
.locals_dict = (mp_obj_t)&rawfile_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
STATIC const mp_stream_p_t textio_stream_p = {
|
||||
.read = fdfile_read,
|
||||
.write = fdfile_write,
|
||||
};
|
||||
|
||||
const mp_obj_type_t mp_type_textio = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_TextIOWrapper,
|
||||
.print = fdfile_print,
|
||||
.make_new = fdfile_make_new,
|
||||
.getiter = mp_identity,
|
||||
.iternext = mp_stream_unbuffered_iter,
|
||||
.stream_p = &textio_stream_p,
|
||||
.locals_dict = (mp_obj_t)&rawfile_locals_dict,
|
||||
};
|
||||
|
||||
// Factory function for I/O stream classes
|
||||
mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args) {
|
||||
// TODO: analyze mode and buffering args and instantiate appropriate type
|
||||
return fdfile_make_new((mp_obj_t)&rawfile_type, n_args, 0, args);
|
||||
return fdfile_make_new((mp_obj_t)&mp_type_textio, n_args, 0, args);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open);
|
||||
|
||||
const mp_obj_fdfile_t mp_sys_stdin_obj = { .base = {&rawfile_type}, .fd = STDIN_FILENO };
|
||||
const mp_obj_fdfile_t mp_sys_stdout_obj = { .base = {&rawfile_type}, .fd = STDOUT_FILENO };
|
||||
const mp_obj_fdfile_t mp_sys_stderr_obj = { .base = {&rawfile_type}, .fd = STDERR_FILENO };
|
||||
const mp_obj_fdfile_t mp_sys_stdin_obj = { .base = {&mp_type_textio}, .fd = STDIN_FILENO };
|
||||
const mp_obj_fdfile_t mp_sys_stdout_obj = { .base = {&mp_type_textio}, .fd = STDOUT_FILENO };
|
||||
const mp_obj_fdfile_t mp_sys_stderr_obj = { .base = {&mp_type_textio}, .fd = STDERR_FILENO };
|
||||
|
@ -45,6 +45,7 @@
|
||||
#define MICROPY_MOD_SYS_EXIT (1)
|
||||
#define MICROPY_MOD_SYS_STDFILES (1)
|
||||
#define MICROPY_ENABLE_MOD_CMATH (1)
|
||||
#define MICROPY_MOD_IO_FILEIO (1)
|
||||
// Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc.
|
||||
// names in exception messages (may require more RAM).
|
||||
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED)
|
||||
|
Loading…
Reference in New Issue
Block a user