kopia lustrzana https://github.com/micropython/micropython
py: Add native json printing using existing print framework.
Also add start of ujson module with dumps implemented. Enabled in unix and stmhal ports. Test passes on both.pull/815/head
rodzic
8a9b999f1c
commit
612045f53f
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#if MICROPY_PY_UJSON
|
||||
|
||||
STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
|
||||
vstr_t vstr;
|
||||
vstr_init(&vstr, 8);
|
||||
mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, &vstr, obj, PRINT_JSON);
|
||||
mp_obj_t ret = mp_obj_new_str(vstr.buf, vstr.len, false);
|
||||
vstr_clear(&vstr);
|
||||
return ret;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_ujson_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ujson) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dumps), (mp_obj_t)&mod_ujson_dumps_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_ujson_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_ujson_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_ujson_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_ujson_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
const mp_obj_module_t mp_module_ujson = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_ujson,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_ujson_globals,
|
||||
};
|
||||
|
||||
#endif //MICROPY_PY_UJSON
|
|
@ -89,3 +89,4 @@ extern struct _dummy_t mp_sys_stderr_obj;
|
|||
// extmod modules
|
||||
extern const mp_obj_module_t mp_module_uctypes;
|
||||
extern const mp_obj_module_t mp_module_zlibd;
|
||||
extern const mp_obj_module_t mp_module_ujson;
|
||||
|
|
|
@ -200,6 +200,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
|
|||
#if MICROPY_PY_ZLIBD
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_zlibd), (mp_obj_t)&mp_module_zlibd },
|
||||
#endif
|
||||
#if MICROPY_PY_UJSON
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ujson), (mp_obj_t)&mp_module_ujson },
|
||||
#endif
|
||||
|
||||
// extra builtin modules as defined by a port
|
||||
MICROPY_PORT_BUILTIN_MODULES
|
||||
|
|
|
@ -390,6 +390,10 @@ typedef double mp_float_t;
|
|||
#define MICROPY_PY_ZLIBD (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_UJSON
|
||||
#define MICROPY_PY_UJSON (0)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Hooks for a port to add builtins */
|
||||
|
||||
|
|
3
py/obj.h
3
py/obj.h
|
@ -187,7 +187,8 @@ typedef enum {
|
|||
PRINT_STR = 0,
|
||||
PRINT_REPR = 1,
|
||||
PRINT_EXC = 2, // Special format for printing exception in unhandled exception message
|
||||
PRINT_EXC_SUBCLASS = 4, // Internal flag for printing exception subclasses
|
||||
PRINT_JSON = 3,
|
||||
PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses
|
||||
} mp_print_kind_t;
|
||||
|
||||
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);
|
||||
|
|
|
@ -41,11 +41,19 @@ typedef struct _mp_obj_bool_t {
|
|||
|
||||
STATIC void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
mp_obj_bool_t *self = self_in;
|
||||
if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
|
||||
if (self->value) {
|
||||
print(env, "true");
|
||||
} else {
|
||||
print(env, "false");
|
||||
}
|
||||
} else {
|
||||
if (self->value) {
|
||||
print(env, "True");
|
||||
} else {
|
||||
print(env, "False");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t bool_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
|
|
|
@ -60,6 +60,9 @@ STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, mp_uint_t *cur) {
|
|||
STATIC void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
mp_obj_dict_t *self = self_in;
|
||||
bool first = true;
|
||||
if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
|
||||
kind = PRINT_REPR;
|
||||
}
|
||||
print(env, "{");
|
||||
mp_uint_t cur = 0;
|
||||
mp_map_elem_t *next = NULL;
|
||||
|
@ -68,9 +71,9 @@ STATIC void dict_print(void (*print)(void *env, const char *fmt, ...), void *env
|
|||
print(env, ", ");
|
||||
}
|
||||
first = false;
|
||||
mp_obj_print_helper(print, env, next->key, PRINT_REPR);
|
||||
mp_obj_print_helper(print, env, next->key, kind);
|
||||
print(env, ": ");
|
||||
mp_obj_print_helper(print, env, next->value, PRINT_REPR);
|
||||
mp_obj_print_helper(print, env, next->value, kind);
|
||||
}
|
||||
print(env, "}");
|
||||
}
|
||||
|
|
|
@ -49,12 +49,15 @@ STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args);
|
|||
|
||||
STATIC void list_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
|
||||
mp_obj_list_t *o = o_in;
|
||||
if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
|
||||
kind = PRINT_REPR;
|
||||
}
|
||||
print(env, "[");
|
||||
for (mp_uint_t i = 0; i < o->len; i++) {
|
||||
if (i > 0) {
|
||||
print(env, ", ");
|
||||
}
|
||||
mp_obj_print_helper(print, env, o->items[i], PRINT_REPR);
|
||||
mp_obj_print_helper(print, env, o->items[i], kind);
|
||||
}
|
||||
print(env, "]");
|
||||
}
|
||||
|
|
|
@ -38,7 +38,11 @@ typedef struct _mp_obj_none_t {
|
|||
} mp_obj_none_t;
|
||||
|
||||
STATIC void none_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
|
||||
print(env, "null");
|
||||
} else {
|
||||
print(env, "None");
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t none_unary_op(mp_uint_t op, mp_obj_t o_in) {
|
||||
|
|
32
py/objstr.c
32
py/objstr.c
|
@ -92,9 +92,41 @@ void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *e
|
|||
print(env, "%c", quote_char);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_UJSON
|
||||
STATIC void str_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, mp_uint_t str_len) {
|
||||
print(env, "\"");
|
||||
for (const byte *s = str_data, *top = str_data + str_len; s < top; s++) {
|
||||
if (*s == '"' || *s == '\\' || *s == '/') {
|
||||
print(env, "\\%c", *s);
|
||||
} else if (32 <= *s && *s <= 126) {
|
||||
print(env, "%c", *s);
|
||||
} else if (*s == '\b') {
|
||||
print(env, "\\b");
|
||||
} else if (*s == '\f') {
|
||||
print(env, "\\f");
|
||||
} else if (*s == '\n') {
|
||||
print(env, "\\n");
|
||||
} else if (*s == '\r') {
|
||||
print(env, "\\r");
|
||||
} else if (*s == '\t') {
|
||||
print(env, "\\t");
|
||||
} else {
|
||||
print(env, "\\u%04x", *s);
|
||||
}
|
||||
}
|
||||
print(env, "\"");
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
GET_STR_DATA_LEN(self_in, str_data, str_len);
|
||||
bool is_bytes = MP_OBJ_IS_TYPE(self_in, &mp_type_bytes);
|
||||
#if MICROPY_PY_UJSON
|
||||
if (kind == PRINT_JSON) {
|
||||
str_print_json(print, env, str_data, str_len);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (kind == PRINT_STR && !is_bytes) {
|
||||
print(env, "%.*s", str_len, str_data);
|
||||
} else {
|
||||
|
|
|
@ -91,8 +91,44 @@ STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), voi
|
|||
print(env, "%c", quote_char);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_UJSON
|
||||
STATIC void uni_print_json(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
|
||||
print(env, "\"");
|
||||
const byte *s = str_data, *top = str_data + str_len;
|
||||
while (s < top) {
|
||||
unichar ch;
|
||||
ch = utf8_get_char(s);
|
||||
s = utf8_next_char(s);
|
||||
if (ch == '"' || ch == '\\' || ch == '/') {
|
||||
print(env, "\\%c", ch);
|
||||
} else if (32 <= ch && ch <= 126) {
|
||||
print(env, "%c", ch);
|
||||
} else if (*s == '\b') {
|
||||
print(env, "\\b");
|
||||
} else if (*s == '\f') {
|
||||
print(env, "\\f");
|
||||
} else if (*s == '\n') {
|
||||
print(env, "\\n");
|
||||
} else if (*s == '\r') {
|
||||
print(env, "\\r");
|
||||
} else if (*s == '\t') {
|
||||
print(env, "\\t");
|
||||
} else {
|
||||
print(env, "\\u%04x", ch);
|
||||
}
|
||||
}
|
||||
print(env, "\"");
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC void uni_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
GET_STR_DATA_LEN(self_in, str_data, str_len);
|
||||
#if MICROPY_PY_UJSON
|
||||
if (kind == PRINT_JSON) {
|
||||
uni_print_json(print, env, str_data, str_len);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (kind == PRINT_STR) {
|
||||
print(env, "%.*s", str_len, str_data);
|
||||
} else {
|
||||
|
|
|
@ -43,17 +43,26 @@ STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, mp_uint_t cur);
|
|||
|
||||
void mp_obj_tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
|
||||
mp_obj_tuple_t *o = o_in;
|
||||
if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
|
||||
print(env, "[");
|
||||
} else {
|
||||
print(env, "(");
|
||||
kind = PRINT_REPR;
|
||||
}
|
||||
for (mp_uint_t i = 0; i < o->len; i++) {
|
||||
if (i > 0) {
|
||||
print(env, ", ");
|
||||
}
|
||||
mp_obj_print_helper(print, env, o->items[i], PRINT_REPR);
|
||||
mp_obj_print_helper(print, env, o->items[i], kind);
|
||||
}
|
||||
if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
|
||||
print(env, "]");
|
||||
} else {
|
||||
if (o->len == 1) {
|
||||
print(env, ",");
|
||||
}
|
||||
print(env, ")");
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
|
|
1
py/py.mk
1
py/py.mk
|
@ -112,6 +112,7 @@ PY_O_BASENAME = \
|
|||
pfenv_printf.o \
|
||||
../extmod/moductypes.o \
|
||||
../extmod/modzlibd.o \
|
||||
../extmod/modujson.o \
|
||||
|
||||
# prepend the build destination prefix to the py object files
|
||||
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
|
||||
|
|
|
@ -463,3 +463,8 @@ Q(deleter)
|
|||
Q(zlibd)
|
||||
Q(decompress)
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UJSON
|
||||
Q(ujson)
|
||||
Q(dumps)
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#define MICROPY_PY_IO_FILEIO (1)
|
||||
#define MICROPY_PY_UCTYPES (1)
|
||||
#define MICROPY_PY_ZLIBD (1)
|
||||
#define MICROPY_PY_UJSON (1)
|
||||
|
||||
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
|
||||
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
try:
|
||||
import ujson as json
|
||||
except ImportError:
|
||||
import json
|
||||
|
||||
print(json.dumps(False))
|
||||
print(json.dumps(True))
|
||||
print(json.dumps(None))
|
||||
print(json.dumps(1))
|
||||
print(json.dumps(1.2))
|
||||
print(json.dumps('abc'))
|
||||
print(json.dumps('\x01\x7e\x7f\x80\u1234'))
|
||||
print(json.dumps([]))
|
||||
print(json.dumps([1]))
|
||||
print(json.dumps([1, 2]))
|
||||
print(json.dumps([1, True]))
|
||||
print(json.dumps(()))
|
||||
print(json.dumps((1,)))
|
||||
print(json.dumps((1, 2)))
|
||||
print(json.dumps((1, (2, 3))))
|
||||
print(json.dumps({}))
|
||||
print(json.dumps({"a":1}))
|
||||
print(json.dumps({"a":(2,[3,None])}))
|
|
@ -3,6 +3,7 @@
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import platform
|
||||
import argparse
|
||||
from glob import glob
|
||||
|
||||
|
@ -37,6 +38,11 @@ def run_tests(pyb, tests, args):
|
|||
if pyb is not None:
|
||||
skip_tests.add('float/float_divmod.py') # tested by float/float_divmod_relaxed.py instead
|
||||
|
||||
# Some tests are known to fail on 64-bit machines
|
||||
if pyb is None and platform.architecture()[0] == '64bit':
|
||||
skip_tests.add('extmod/uctypes_ptr_le.py')
|
||||
skip_tests.add('extmod/uctypes_ptr_native_le.py')
|
||||
|
||||
# Some tests are known to fail with native emitter
|
||||
# Remove them from the below when they work
|
||||
if args.emit == 'native':
|
||||
|
@ -153,10 +159,10 @@ def main():
|
|||
if args.test_dirs is None:
|
||||
if pyb is None:
|
||||
# run PC tests
|
||||
test_dirs = ('basics', 'micropython', 'float', 'import', 'io', 'misc', 'unicode', 'unix')
|
||||
test_dirs = ('basics', 'micropython', 'float', 'import', 'io', 'misc', 'unicode', 'extmod', 'unix')
|
||||
else:
|
||||
# run pyboard tests
|
||||
test_dirs = ('basics', 'micropython', 'float', 'misc', 'pyb', 'pybnative', 'inlineasm')
|
||||
test_dirs = ('basics', 'micropython', 'float', 'misc', 'extmod', 'pyb', 'pybnative', 'inlineasm')
|
||||
else:
|
||||
# run tests from these directories
|
||||
test_dirs = args.test_dirs
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
|
||||
#define MICROPY_PY_UCTYPES (1)
|
||||
#define MICROPY_PY_ZLIBD (1)
|
||||
#define MICROPY_PY_UJSON (1)
|
||||
|
||||
// Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc.
|
||||
// names in exception messages (may require more RAM).
|
||||
|
|
Ładowanie…
Reference in New Issue