circuitpython/tests/micropython/import_mpy_native_x64.py
Damien George c49d5207e9 py/persistentcode: Remove unicode feature flag from .mpy file.
Prior to this commit, even with unicode disabled .py and .mpy files could
contain unicode characters, eg by entering them directly in a string as
utf-8 encoded.

The only thing the compiler disallowed (with unicode disabled) was using
\uxxxx and \Uxxxxxxxx notation to specify a character within a string with
value >= 0x100; that would give a SyntaxError.

With this change mpy-cross will now accept \u and \U notation to insert a
character with value >= 0x100 into a string (because the -mno-unicode
option is now gone, there's no way to forbid this).  The runtime will
happily work with strings with such characters, just like it already works
with strings with characters that were utf-8 encoded directly.

This change simplifies things because there are no longer any feature
flags in .mpy files, and any bytecode .mpy will now run on any target.

Signed-off-by: Damien George <damien@micropython.org>
2022-05-17 12:51:54 +10:00

131 lines
3.3 KiB
Python

# test importing of .mpy files with native code (x64 only)
try:
import usys, uio, uos
uio.IOBase
uos.mount
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
if not (usys.platform == "linux" and usys.maxsize > 2**32):
print("SKIP")
raise SystemExit
class UserFile(uio.IOBase):
def __init__(self, data):
self.data = memoryview(data)
self.pos = 0
def readinto(self, buf):
n = min(len(buf), len(self.data) - self.pos)
buf[:n] = self.data[self.pos : self.pos + n]
self.pos += n
return n
def ioctl(self, req, arg):
return 0
class UserFS:
def __init__(self, files):
self.files = files
def mount(self, readonly, mksfs):
pass
def umount(self):
pass
def stat(self, path):
if path in self.files:
return (32768, 0, 0, 0, 0, 0, 0, 0, 0, 0)
raise OSError
def open(self, path, mode):
return UserFile(self.files[path])
# these are the test .mpy files
# fmt: off
user_files = {
# bad architecture
'/mod0.mpy': b'M\x06\xfc\x00\x10',
# test loading of viper and asm
'/mod1.mpy': (
b'M\x06\x08\x1f' # header
b'\x02' # n_qstr
b'\x00' # n_obj
b'\x0emod1.py\x00' # qstr0 = "mod1.py"
b'\x0aouter\x00' # qstr1 = "outer"
b'\x2c' # 5 bytes, have children, bytecode
b'\x00\x02' # prelude
b'\x01' # simple name (qstr index)
b'\x51' # LOAD_CONST_NONE
b'\x63' # RETURN_VALUE
b'\x02' # 2 children
b'\x42' # 8 bytes, no children, viper code
b'\x00\x00\x00\x00\x00\x00' # dummy machine code
b'\x00\x00' # slot for qstr0
b'\x01\x0c\x0aprint\x00' # n_qstr=1, qstr0
b'\x00' # scope_flags
b'\x43' # 8 bytes, no children, asm code
b'\x00\x00\x00\x00\x00\x00\x00\x00' # dummy machine code
b'\x00\x00\x00' # scope_flags, n_pos_args, type_sig
),
# test loading viper with additional scope flags and relocation
'/mod2.mpy': (
b'M\x06\x08\x1f' # header
b'\x02' # n_qstr
b'\x00' # n_obj
b'\x0emod2.py\x00' # qstr0 = "mod2.py"
b'\x0aouter\x00' # qstr1 = "outer"
b'\x2c' # 5 bytes, have children, bytecode
b'\x00\x02' # prelude
b'\x01' # simple name (qstr index)
b'\x51' # LOAD_CONST_NONE
b'\x63' # RETURN_VALUE
b'\x01' # 1 child
b'\x22' # 4 bytes, no children, viper code
b'\x00\x00\x00\x00' # dummy machine code
b'\x00' # n_qstr=0
b'\x70' # scope_flags: VIPERBSS | VIPERRODATA | VIPERRELOC
b'\x06\x04' # rodata=6 bytes, bss=4 bytes
b'rodata' # rodata content
b'\x03\x01\x00' # dummy relocation of rodata
),
}
# fmt: on
# create and mount a user filesystem
uos.mount(UserFS(user_files), "/userfs")
usys.path.append("/userfs")
# import .mpy files from the user filesystem
for i in range(len(user_files)):
mod = "mod%u" % i
try:
__import__(mod)
print(mod, "OK")
except ValueError as er:
print(mod, "ValueError", er)
# unmount and undo path addition
uos.umount("/userfs")
usys.path.pop()