mirror of
https://github.com/pocketpy/pocketpy
synced 2025-11-09 13:10:17 +00:00
Compare commits
8 Commits
9ecfc0196f
...
c9d7525ec2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9d7525ec2 | ||
|
|
8751e82ee0 | ||
|
|
e51e152b8c | ||
|
|
9ff3417621 | ||
|
|
3afab89ab3 | ||
|
|
eba88e5541 | ||
|
|
92d3a589e8 | ||
|
|
6264776999 |
13
.github/workflows/main.yml
vendored
13
.github/workflows/main.yml
vendored
@ -96,13 +96,14 @@ jobs:
|
|||||||
- name: Build and Test
|
- name: Build and Test
|
||||||
run: |
|
run: |
|
||||||
uname -m
|
uname -m
|
||||||
|
python -c "import struct; print(8 * struct.calcsize('P'))"
|
||||||
|
|
||||||
python cmake_build.py Debug
|
# python cmake_build.py Debug
|
||||||
# gdb_commands.txt
|
# # gdb_commands.txt
|
||||||
echo "run" > gdb_commands.txt
|
# echo "run" > gdb_commands.txt
|
||||||
echo "backtrace" >> gdb_commands.txt
|
# echo "backtrace" >> gdb_commands.txt
|
||||||
echo "quit" >> gdb_commands.txt
|
# echo "quit" >> gdb_commands.txt
|
||||||
gdb -batch -x gdb_commands.txt --args ./main tests/77_builtin_func_1.py
|
# gdb -batch -x gdb_commands.txt --args ./main tests/77_builtin_func_1.py
|
||||||
|
|
||||||
python cmake_build.py
|
python cmake_build.py
|
||||||
python scripts/run_tests.py
|
python scripts/run_tests.py
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
python prebuild.py
|
# python prebuild.py
|
||||||
|
|
||||||
SRC=$(find src/ -name "*.c")
|
SRC=$(find src/ -name "*.c")
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
python prebuild.py
|
# python prebuild.py
|
||||||
|
|
||||||
SRC=$(find src/ -name "*.c")
|
SRC=$(find src/ -name "*.c")
|
||||||
|
|
||||||
FLAGS="-std=c11 -lm -ldl -I3rd/lz4 -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1 -DPK_BUILD_MODULE_LZ4"
|
FLAGS="-std=c11 -lm -ldl -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1"
|
||||||
|
|
||||||
SANITIZE_FLAGS="-fsanitize=address,leak,undefined"
|
SANITIZE_FLAGS="-fsanitize=address,leak,undefined"
|
||||||
|
|
||||||
@ -13,5 +13,5 @@ if [ "$(uname)" == "Darwin" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Compiling C files..."
|
echo "Compiling C files..."
|
||||||
gcc -m32 $FLAGS $SANITIZE_FLAGS $SRC src2/main.c 3rd/lz4/lz4libs/lz4.c -o main
|
gcc -m32 $FLAGS $SANITIZE_FLAGS $SRC src2/main.c -o main
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ output: .retype
|
|||||||
url: https://pocketpy.dev
|
url: https://pocketpy.dev
|
||||||
branding:
|
branding:
|
||||||
title: pocketpy
|
title: pocketpy
|
||||||
label: v2.0.6
|
label: v2.0.7
|
||||||
logo: "./static/logo.png"
|
logo: "./static/logo.png"
|
||||||
favicon: "./static/logo.png"
|
favicon: "./static/logo.png"
|
||||||
meta:
|
meta:
|
||||||
|
|||||||
@ -8,8 +8,6 @@ MAGIC_METHOD(__ge__)
|
|||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
MAGIC_METHOD(__neg__)
|
MAGIC_METHOD(__neg__)
|
||||||
MAGIC_METHOD(__abs__)
|
MAGIC_METHOD(__abs__)
|
||||||
MAGIC_METHOD(__float__)
|
|
||||||
MAGIC_METHOD(__int__)
|
|
||||||
MAGIC_METHOD(__round__)
|
MAGIC_METHOD(__round__)
|
||||||
MAGIC_METHOD(__divmod__)
|
MAGIC_METHOD(__divmod__)
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|||||||
@ -103,15 +103,6 @@ class PocketpyBindings {
|
|||||||
late final _py_setvmctx =
|
late final _py_setvmctx =
|
||||||
_py_setvmctxPtr.asFunction<void Function(ffi.Pointer<ffi.Void>)>();
|
_py_setvmctxPtr.asFunction<void Function(ffi.Pointer<ffi.Void>)>();
|
||||||
|
|
||||||
/// Interrupt the current VM and raise a `KeyboardInterrupt` exception.
|
|
||||||
void py_interrupt() {
|
|
||||||
return _py_interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
late final _py_interruptPtr =
|
|
||||||
_lookup<ffi.NativeFunction<ffi.Void Function()>>('py_interrupt');
|
|
||||||
late final _py_interrupt = _py_interruptPtr.asFunction<void Function()>();
|
|
||||||
|
|
||||||
/// Set `sys.argv`. Used for storing command-line arguments.
|
/// Set `sys.argv`. Used for storing command-line arguments.
|
||||||
void py_sys_setargv(
|
void py_sys_setargv(
|
||||||
int argc,
|
int argc,
|
||||||
@ -130,6 +121,21 @@ class PocketpyBindings {
|
|||||||
late final _py_sys_setargv = _py_sys_setargvPtr
|
late final _py_sys_setargv = _py_sys_setargvPtr
|
||||||
.asFunction<void Function(int, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();
|
.asFunction<void Function(int, ffi.Pointer<ffi.Pointer<ffi.Char>>)>();
|
||||||
|
|
||||||
|
/// Set the trace function for the current VM.
|
||||||
|
void py_sys_settrace(
|
||||||
|
py_TraceFunc func,
|
||||||
|
) {
|
||||||
|
return _py_sys_settrace(
|
||||||
|
func,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final _py_sys_settracePtr =
|
||||||
|
_lookup<ffi.NativeFunction<ffi.Void Function(py_TraceFunc)>>(
|
||||||
|
'py_sys_settrace');
|
||||||
|
late final _py_sys_settrace =
|
||||||
|
_py_sys_settracePtr.asFunction<void Function(py_TraceFunc)>();
|
||||||
|
|
||||||
/// Setup the callbacks for the current VM.
|
/// Setup the callbacks for the current VM.
|
||||||
ffi.Pointer<py_Callbacks> py_callbacks() {
|
ffi.Pointer<py_Callbacks> py_callbacks() {
|
||||||
return _py_callbacks();
|
return _py_callbacks();
|
||||||
@ -141,6 +147,41 @@ class PocketpyBindings {
|
|||||||
late final _py_callbacks =
|
late final _py_callbacks =
|
||||||
_py_callbacksPtr.asFunction<ffi.Pointer<py_Callbacks> Function()>();
|
_py_callbacksPtr.asFunction<ffi.Pointer<py_Callbacks> Function()>();
|
||||||
|
|
||||||
|
/// Get the current source location of the frame.
|
||||||
|
ffi.Pointer<ffi.Char> py_Frame_sourceloc(
|
||||||
|
ffi.Pointer<py_Frame> frame,
|
||||||
|
ffi.Pointer<ffi.Int> lineno,
|
||||||
|
) {
|
||||||
|
return _py_Frame_sourceloc(
|
||||||
|
frame,
|
||||||
|
lineno,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final _py_Frame_sourcelocPtr = _lookup<
|
||||||
|
ffi.NativeFunction<
|
||||||
|
ffi.Pointer<ffi.Char> Function(ffi.Pointer<py_Frame>,
|
||||||
|
ffi.Pointer<ffi.Int>)>>('py_Frame_sourceloc');
|
||||||
|
late final _py_Frame_sourceloc = _py_Frame_sourcelocPtr.asFunction<
|
||||||
|
ffi.Pointer<ffi.Char> Function(
|
||||||
|
ffi.Pointer<py_Frame>, ffi.Pointer<ffi.Int>)>();
|
||||||
|
|
||||||
|
/// Get the function object of the frame.
|
||||||
|
/// Returns `NULL` if not available.
|
||||||
|
py_StackRef py_Frame_function(
|
||||||
|
ffi.Pointer<py_Frame> frame,
|
||||||
|
) {
|
||||||
|
return _py_Frame_function(
|
||||||
|
frame,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final _py_Frame_functionPtr =
|
||||||
|
_lookup<ffi.NativeFunction<py_StackRef Function(ffi.Pointer<py_Frame>)>>(
|
||||||
|
'py_Frame_function');
|
||||||
|
late final _py_Frame_function = _py_Frame_functionPtr
|
||||||
|
.asFunction<py_StackRef Function(ffi.Pointer<py_Frame>)>();
|
||||||
|
|
||||||
/// Run a source string.
|
/// Run a source string.
|
||||||
/// @param source source string.
|
/// @param source source string.
|
||||||
/// @param filename filename (for error messages).
|
/// @param filename filename (for error messages).
|
||||||
@ -1474,6 +1515,18 @@ class PocketpyBindings {
|
|||||||
late final _py_inspect_currentmodule =
|
late final _py_inspect_currentmodule =
|
||||||
_py_inspect_currentmodulePtr.asFunction<py_GlobalRef Function()>();
|
_py_inspect_currentmodulePtr.asFunction<py_GlobalRef Function()>();
|
||||||
|
|
||||||
|
/// Get the current frame object.
|
||||||
|
/// Return `NULL` if not available.
|
||||||
|
ffi.Pointer<py_Frame> py_inspect_currentframe() {
|
||||||
|
return _py_inspect_currentframe();
|
||||||
|
}
|
||||||
|
|
||||||
|
late final _py_inspect_currentframePtr =
|
||||||
|
_lookup<ffi.NativeFunction<ffi.Pointer<py_Frame> Function()>>(
|
||||||
|
'py_inspect_currentframe');
|
||||||
|
late final _py_inspect_currentframe = _py_inspect_currentframePtr
|
||||||
|
.asFunction<ffi.Pointer<py_Frame> Function()>();
|
||||||
|
|
||||||
/// Bind a function to the object via "decl-based" style.
|
/// Bind a function to the object via "decl-based" style.
|
||||||
/// @param obj the target object.
|
/// @param obj the target object.
|
||||||
/// @param sig signature of the function. e.g. `add(x, y)`.
|
/// @param sig signature of the function. e.g. `add(x, y)`.
|
||||||
@ -1828,9 +1881,10 @@ class PocketpyBindings {
|
|||||||
_py_pushmethodPtr.asFunction<bool Function(int)>();
|
_py_pushmethodPtr.asFunction<bool Function(int)>();
|
||||||
|
|
||||||
/// Call a callable object via pocketpy's calling convention.
|
/// Call a callable object via pocketpy's calling convention.
|
||||||
/// You need to prepare the stack using this form: `callable, self/nil, arg1, arg2, ..., k1, v1, k2, v2, ...`
|
/// You need to prepare the stack using the following format:
|
||||||
|
/// `callable, self/nil, arg1, arg2, ..., k1, v1, k2, v2, ...`.
|
||||||
/// `argc` is the number of positional arguments excluding `self`.
|
/// `argc` is the number of positional arguments excluding `self`.
|
||||||
/// `kwargc` is the number of keyword arguments, i.e. the number of key-value pairs.
|
/// `kwargc` is the number of keyword arguments.
|
||||||
/// The result will be set to `py_retval()`.
|
/// The result will be set to `py_retval()`.
|
||||||
/// The stack size will be reduced by `2 + argc + kwargc * 2`.
|
/// The stack size will be reduced by `2 + argc + kwargc * 2`.
|
||||||
bool py_vectorcall(
|
bool py_vectorcall(
|
||||||
@ -1947,7 +2001,7 @@ class PocketpyBindings {
|
|||||||
late final _py_exception =
|
late final _py_exception =
|
||||||
_py_exceptionPtr.asFunction<bool Function(int, ffi.Pointer<ffi.Char>)>();
|
_py_exceptionPtr.asFunction<bool Function(int, ffi.Pointer<ffi.Char>)>();
|
||||||
|
|
||||||
/// Raise an expection object. Always return false.
|
/// Raise an exception object. Always return false.
|
||||||
bool py_raise(
|
bool py_raise(
|
||||||
py_Ref arg0,
|
py_Ref arg0,
|
||||||
) {
|
) {
|
||||||
@ -3013,6 +3067,16 @@ final class c11_sv extends ffi.Struct {
|
|||||||
external int size;
|
external int size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class py_Frame extends ffi.Opaque {}
|
||||||
|
|
||||||
|
/// An enum for tracing events.
|
||||||
|
abstract class py_TraceEvent {
|
||||||
|
static const int TRACE_EVENT_LINE = 0;
|
||||||
|
static const int TRACE_EVENT_EXCEPTION = 1;
|
||||||
|
static const int TRACE_EVENT_PUSH = 2;
|
||||||
|
static const int TRACE_EVENT_POP = 3;
|
||||||
|
}
|
||||||
|
|
||||||
/// A struct contains the callbacks of the VM.
|
/// A struct contains the callbacks of the VM.
|
||||||
final class py_Callbacks extends ffi.Struct {
|
final class py_Callbacks extends ffi.Struct {
|
||||||
/// Used by `__import__` to load source code of a module.
|
/// Used by `__import__` to load source code of a module.
|
||||||
@ -3039,6 +3103,12 @@ abstract class py_CompileMode {
|
|||||||
static const int SINGLE_MODE = 2;
|
static const int SINGLE_MODE = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef py_TraceFunc = ffi.Pointer<
|
||||||
|
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<py_Frame>, ffi.Int32)>>;
|
||||||
|
|
||||||
|
/// A specific location in the value stack of the VM.
|
||||||
|
typedef py_StackRef = ffi.Pointer<py_TValue>;
|
||||||
|
|
||||||
/// A generic reference to a python object.
|
/// A generic reference to a python object.
|
||||||
typedef py_Ref = ffi.Pointer<py_TValue>;
|
typedef py_Ref = ffi.Pointer<py_TValue>;
|
||||||
|
|
||||||
@ -3064,9 +3134,6 @@ typedef py_ObjectRef = ffi.Pointer<py_TValue>;
|
|||||||
typedef py_CFunction = ffi.Pointer<
|
typedef py_CFunction = ffi.Pointer<
|
||||||
ffi.NativeFunction<ffi.Bool Function(ffi.Int argc, py_StackRef argv)>>;
|
ffi.NativeFunction<ffi.Bool Function(ffi.Int argc, py_StackRef argv)>>;
|
||||||
|
|
||||||
/// A specific location in the value stack of the VM.
|
|
||||||
typedef py_StackRef = ffi.Pointer<py_TValue>;
|
|
||||||
|
|
||||||
/// An integer that represents a python identifier. This is to achieve string pooling and fast name
|
/// An integer that represents a python identifier. This is to achieve string pooling and fast name
|
||||||
/// resolution.
|
/// resolution.
|
||||||
typedef py_Name = ffi.Uint16;
|
typedef py_Name = ffi.Uint16;
|
||||||
@ -3092,9 +3159,9 @@ typedef py_ItemRef = ffi.Pointer<py_TValue>;
|
|||||||
/// %p: void*
|
/// %p: void*
|
||||||
/// %t: py_Type
|
/// %t: py_Type
|
||||||
/// %n: py_Name
|
/// %n: py_Name
|
||||||
abstract class py_MagicNames {
|
abstract class py_MagicName {
|
||||||
/// 0 is reserved
|
/// 0 is reserved
|
||||||
static const int py_MagicNames__NULL = 0;
|
static const int py_MagicName__NULL = 0;
|
||||||
|
|
||||||
/// math operators
|
/// math operators
|
||||||
static const int __lt__ = 1;
|
static const int __lt__ = 1;
|
||||||
@ -3105,70 +3172,68 @@ abstract class py_MagicNames {
|
|||||||
/// //////////////////////////
|
/// //////////////////////////
|
||||||
static const int __neg__ = 5;
|
static const int __neg__ = 5;
|
||||||
static const int __abs__ = 6;
|
static const int __abs__ = 6;
|
||||||
static const int __float__ = 7;
|
static const int __round__ = 7;
|
||||||
static const int __int__ = 8;
|
static const int __divmod__ = 8;
|
||||||
static const int __round__ = 9;
|
|
||||||
static const int __divmod__ = 10;
|
|
||||||
|
|
||||||
/// //////////////////////////
|
/// //////////////////////////
|
||||||
static const int __add__ = 11;
|
static const int __add__ = 9;
|
||||||
static const int __radd__ = 12;
|
static const int __radd__ = 10;
|
||||||
static const int __sub__ = 13;
|
static const int __sub__ = 11;
|
||||||
static const int __rsub__ = 14;
|
static const int __rsub__ = 12;
|
||||||
static const int __mul__ = 15;
|
static const int __mul__ = 13;
|
||||||
static const int __rmul__ = 16;
|
static const int __rmul__ = 14;
|
||||||
static const int __truediv__ = 17;
|
static const int __truediv__ = 15;
|
||||||
static const int __rtruediv__ = 18;
|
static const int __rtruediv__ = 16;
|
||||||
static const int __floordiv__ = 19;
|
static const int __floordiv__ = 17;
|
||||||
static const int __rfloordiv__ = 20;
|
static const int __rfloordiv__ = 18;
|
||||||
static const int __mod__ = 21;
|
static const int __mod__ = 19;
|
||||||
static const int __rmod__ = 22;
|
static const int __rmod__ = 20;
|
||||||
static const int __pow__ = 23;
|
static const int __pow__ = 21;
|
||||||
static const int __rpow__ = 24;
|
static const int __rpow__ = 22;
|
||||||
static const int __matmul__ = 25;
|
static const int __matmul__ = 23;
|
||||||
static const int __lshift__ = 26;
|
static const int __lshift__ = 24;
|
||||||
static const int __rshift__ = 27;
|
static const int __rshift__ = 25;
|
||||||
static const int __and__ = 28;
|
static const int __and__ = 26;
|
||||||
static const int __or__ = 29;
|
static const int __or__ = 27;
|
||||||
static const int __xor__ = 30;
|
static const int __xor__ = 28;
|
||||||
|
|
||||||
/// //////////////////////////
|
/// //////////////////////////
|
||||||
static const int __repr__ = 31;
|
static const int __repr__ = 29;
|
||||||
static const int __str__ = 32;
|
static const int __str__ = 30;
|
||||||
static const int __hash__ = 33;
|
static const int __hash__ = 31;
|
||||||
static const int __len__ = 34;
|
static const int __len__ = 32;
|
||||||
static const int __iter__ = 35;
|
static const int __iter__ = 33;
|
||||||
static const int __next__ = 36;
|
static const int __next__ = 34;
|
||||||
static const int __contains__ = 37;
|
static const int __contains__ = 35;
|
||||||
static const int __bool__ = 38;
|
static const int __bool__ = 36;
|
||||||
static const int __invert__ = 39;
|
static const int __invert__ = 37;
|
||||||
|
|
||||||
/// //////////////////////////
|
/// //////////////////////////
|
||||||
static const int __eq__ = 40;
|
static const int __eq__ = 38;
|
||||||
static const int __ne__ = 41;
|
static const int __ne__ = 39;
|
||||||
|
|
||||||
/// indexer
|
/// indexer
|
||||||
static const int __getitem__ = 42;
|
static const int __getitem__ = 40;
|
||||||
static const int __setitem__ = 43;
|
static const int __setitem__ = 41;
|
||||||
static const int __delitem__ = 44;
|
static const int __delitem__ = 42;
|
||||||
|
|
||||||
/// specials
|
/// specials
|
||||||
static const int __new__ = 45;
|
static const int __new__ = 43;
|
||||||
static const int __init__ = 46;
|
static const int __init__ = 44;
|
||||||
static const int __call__ = 47;
|
static const int __call__ = 45;
|
||||||
static const int __enter__ = 48;
|
static const int __enter__ = 46;
|
||||||
static const int __exit__ = 49;
|
static const int __exit__ = 47;
|
||||||
static const int __name__ = 50;
|
static const int __name__ = 48;
|
||||||
static const int __all__ = 51;
|
static const int __all__ = 49;
|
||||||
static const int __package__ = 52;
|
static const int __package__ = 50;
|
||||||
static const int __path__ = 53;
|
static const int __path__ = 51;
|
||||||
static const int __class__ = 54;
|
static const int __class__ = 52;
|
||||||
static const int __getattr__ = 55;
|
static const int __getattr__ = 53;
|
||||||
static const int __reduce__ = 56;
|
static const int __reduce__ = 54;
|
||||||
static const int __missing__ = 57;
|
static const int __missing__ = 55;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class py_PredefinedTypes {
|
abstract class py_PredefinedType {
|
||||||
static const int tp_nil = 0;
|
static const int tp_nil = 0;
|
||||||
static const int tp_object = 1;
|
static const int tp_object = 1;
|
||||||
|
|
||||||
@ -3234,7 +3299,7 @@ abstract class py_PredefinedTypes {
|
|||||||
static const int tp_KeyboardInterrupt = 36;
|
static const int tp_KeyboardInterrupt = 36;
|
||||||
static const int tp_StopIteration = 37;
|
static const int tp_StopIteration = 37;
|
||||||
static const int tp_SyntaxError = 38;
|
static const int tp_SyntaxError = 38;
|
||||||
static const int tp_StackOverflowError = 39;
|
static const int tp_RecursionError = 39;
|
||||||
static const int tp_OSError = 40;
|
static const int tp_OSError = 40;
|
||||||
static const int tp_NotImplementedError = 41;
|
static const int tp_NotImplementedError = 41;
|
||||||
static const int tp_TypeError = 42;
|
static const int tp_TypeError = 42;
|
||||||
@ -3264,19 +3329,19 @@ abstract class py_PredefinedTypes {
|
|||||||
static const int tp_chunked_array2d = 62;
|
static const int tp_chunked_array2d = 62;
|
||||||
}
|
}
|
||||||
|
|
||||||
const String PK_VERSION = '2.0.6';
|
const String PK_VERSION = '2.0.7';
|
||||||
|
|
||||||
const int PK_VERSION_MAJOR = 2;
|
const int PK_VERSION_MAJOR = 2;
|
||||||
|
|
||||||
const int PK_VERSION_MINOR = 0;
|
const int PK_VERSION_MINOR = 0;
|
||||||
|
|
||||||
const int PK_VERSION_PATCH = 6;
|
const int PK_VERSION_PATCH = 7;
|
||||||
|
|
||||||
const int PK_LOW_MEMORY_MODE = 0;
|
const int PK_LOW_MEMORY_MODE = 0;
|
||||||
|
|
||||||
const int PK_ENABLE_OS = 1;
|
const int PK_ENABLE_OS = 1;
|
||||||
|
|
||||||
const int PK_GC_MIN_THRESHOLD = 16384;
|
const int PK_GC_MIN_THRESHOLD = 32768;
|
||||||
|
|
||||||
const int PK_VM_STACK_SIZE = 16384;
|
const int PK_VM_STACK_SIZE = 16384;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
name: pocketpy
|
name: pocketpy
|
||||||
description: A lightweight Python interpreter for game engines. It supports Android/iOS/Windows/Linux/MacOS.
|
description: A lightweight Python interpreter for game engines. It supports Android/iOS/Windows/Linux/MacOS.
|
||||||
version: 2.0.6
|
version: 2.0.7
|
||||||
homepage: https://pocketpy.dev
|
homepage: https://pocketpy.dev
|
||||||
repository: https://github.com/pocketpy/pocketpy
|
repository: https://github.com/pocketpy/pocketpy
|
||||||
|
|
||||||
|
|||||||
@ -90,11 +90,6 @@ FrameResult VM__run_top_frame(VM* self) {
|
|||||||
py_exception(tp_RecursionError, "maximum recursion depth exceeded");
|
py_exception(tp_RecursionError, "maximum recursion depth exceeded");
|
||||||
goto __ERROR;
|
goto __ERROR;
|
||||||
}
|
}
|
||||||
if(self->stack.sp >= self->stack.end) {
|
|
||||||
c11__abort(
|
|
||||||
"Stack overflow! Please increase PK_VM_STACK_SIZE or reduce the max recursion limit.");
|
|
||||||
}
|
|
||||||
|
|
||||||
codes = frame->co->codes.data;
|
codes = frame->co->codes.data;
|
||||||
frame->ip++;
|
frame->ip++;
|
||||||
|
|
||||||
|
|||||||
@ -104,6 +104,7 @@ UnwindTarget* Frame__find_unwind_target(py_Frame* self, int iblock) {
|
|||||||
|
|
||||||
void Frame__set_unwind_target(py_Frame* self, py_TValue* sp) {
|
void Frame__set_unwind_target(py_Frame* self, py_TValue* sp) {
|
||||||
int iblock = Frame__iblock(self);
|
int iblock = Frame__iblock(self);
|
||||||
|
assert(iblock >= 0);
|
||||||
UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
|
UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
|
||||||
if(existing) {
|
if(existing) {
|
||||||
existing->offset = sp - self->p0;
|
existing->offset = sp - self->p0;
|
||||||
@ -121,15 +122,14 @@ void Frame__gc_mark(py_Frame* self) {
|
|||||||
|
|
||||||
int Frame__lineno(const py_Frame* self) {
|
int Frame__lineno(const py_Frame* self) {
|
||||||
int ip = self->ip;
|
int ip = self->ip;
|
||||||
if(ip >= 0)
|
if(ip >= 0) return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).lineno;
|
||||||
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).lineno;
|
if(!self->is_locals_special) return self->co->start_line;
|
||||||
if(!self->is_locals_special)
|
|
||||||
return self->co->start_line;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Frame__iblock(const py_Frame* self) {
|
int Frame__iblock(const py_Frame* self) {
|
||||||
int ip = self->ip;
|
int ip = self->ip;
|
||||||
|
if(ip < 0) return -1;
|
||||||
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
|
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -171,9 +171,12 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
|
|||||||
|
|
||||||
if(name == __new__) {
|
if(name == __new__) {
|
||||||
// __new__ acts like a @staticmethod
|
// __new__ acts like a @staticmethod
|
||||||
if(py_istype(self, tp_type)) {
|
if(self->type == tp_type) {
|
||||||
// T.__new__(...)
|
// T.__new__(...)
|
||||||
type = py_totype(self);
|
type = py_totype(self);
|
||||||
|
} else if(self->type == tp_super) {
|
||||||
|
// super(T, obj).__new__(...)
|
||||||
|
type = *(py_Type*)py_touserdata(self);
|
||||||
} else {
|
} else {
|
||||||
// invalid usage of `__new__`
|
// invalid usage of `__new__`
|
||||||
return false;
|
return false;
|
||||||
@ -187,12 +190,16 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
py_TValue self_bak; // to avoid overlapping
|
||||||
// handle super() proxy
|
// handle super() proxy
|
||||||
if(py_istype(self, tp_super)) {
|
if(py_istype(self, tp_super)) {
|
||||||
type = *(py_Type*)py_touserdata(self);
|
type = *(py_Type*)py_touserdata(self);
|
||||||
*self = *py_getslot(self, 0);
|
// BUG: here we modify `self` which refers to the stack directly
|
||||||
|
// If `pk_loadmethod` fails, `self` will be corrupted
|
||||||
|
self_bak = *py_getslot(self, 0);
|
||||||
} else {
|
} else {
|
||||||
type = self->type;
|
type = self->type;
|
||||||
|
self_bak = *self;
|
||||||
}
|
}
|
||||||
|
|
||||||
py_Ref cls_var = py_tpfindname(type, name);
|
py_Ref cls_var = py_tpfindname(type, name);
|
||||||
@ -200,8 +207,6 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
|
|||||||
switch(cls_var->type) {
|
switch(cls_var->type) {
|
||||||
case tp_function:
|
case tp_function:
|
||||||
case tp_nativefunc: {
|
case tp_nativefunc: {
|
||||||
py_TValue self_bak = *self;
|
|
||||||
// `out` may overlap with `self`. If we assign `out`, `self` may be corrupted.
|
|
||||||
self[0] = *cls_var;
|
self[0] = *cls_var;
|
||||||
self[1] = self_bak;
|
self[1] = self_bak;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -283,7 +283,7 @@ static bool dict__init__(int argc, py_Ref argv) {
|
|||||||
for(int i = 0; i < length; i++) {
|
for(int i = 0; i < length; i++) {
|
||||||
py_Ref tuple = &p[i];
|
py_Ref tuple = &p[i];
|
||||||
if(!py_istuple(tuple) || py_tuple_len(tuple) != 2) {
|
if(!py_istuple(tuple) || py_tuple_len(tuple) != 2) {
|
||||||
return TypeError("dict.__init__() argument must be a list of tuple-2");
|
return ValueError("dict.__init__() argument must be a list of tuple-2");
|
||||||
}
|
}
|
||||||
py_Ref key = py_tuple_getitem(tuple, 0);
|
py_Ref key = py_tuple_getitem(tuple, 0);
|
||||||
py_Ref val = py_tuple_getitem(tuple, 1);
|
py_Ref val = py_tuple_getitem(tuple, 1);
|
||||||
|
|||||||
@ -123,9 +123,7 @@ static bool number__pow__(int argc, py_Ref argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static py_i64 i64_abs(py_i64 x) {
|
static py_i64 i64_abs(py_i64 x) { return x < 0 ? -x : x; }
|
||||||
return x < 0 ? -x : x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static py_i64 cpy11__fast_floor_div(py_i64 a, py_i64 b) {
|
static py_i64 cpy11__fast_floor_div(py_i64 a, py_i64 b) {
|
||||||
assert(b != 0);
|
assert(b != 0);
|
||||||
@ -316,7 +314,7 @@ static bool int__new__(int argc, py_Ref argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case tp_str: break; // leave to the next block
|
case tp_str: break; // leave to the next block
|
||||||
default: return pk_callmagic(__int__, 1, argv + 1);
|
default: return TypeError("int() argument must be a string, number or boolean");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 2+ args -> error
|
// 2+ args -> error
|
||||||
@ -388,7 +386,7 @@ static bool float__new__(int argc, py_Ref argv) {
|
|||||||
py_newfloat(py_retval(), float_out);
|
py_newfloat(py_retval(), float_out);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default: return pk_callmagic(__float__, 1, argv + 1);
|
default: return TypeError("float() argument must be a string or a real number");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
48
src2/main.c
48
src2/main.c
@ -2,6 +2,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "pocketpy.h"
|
#include "pocketpy.h"
|
||||||
|
|
||||||
@ -29,7 +30,7 @@ static void sigint_handler(int sig) { py_interrupt(); }
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* read_file(const char* path) {
|
static char* read_file(const char* path) {
|
||||||
FILE* file = fopen(path, "rb");
|
FILE* file = fopen(path, "rb");
|
||||||
if(file == NULL) {
|
if(file == NULL) {
|
||||||
printf("Error: file not found\n");
|
printf("Error: file not found\n");
|
||||||
@ -44,6 +45,27 @@ char* read_file(const char* path) {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tracefunc(py_Frame* frame, enum py_TraceEvent event) {
|
||||||
|
int line;
|
||||||
|
const char* filename = py_Frame_sourceloc(frame, &line);
|
||||||
|
const char* event_str;
|
||||||
|
switch(event) {
|
||||||
|
case TRACE_EVENT_LINE:
|
||||||
|
event_str = "line";
|
||||||
|
break;
|
||||||
|
case TRACE_EVENT_EXCEPTION:
|
||||||
|
event_str = "exception";
|
||||||
|
break;
|
||||||
|
case TRACE_EVENT_PUSH:
|
||||||
|
event_str = "push";
|
||||||
|
break;
|
||||||
|
case TRACE_EVENT_POP:
|
||||||
|
event_str = "pop";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("\x1b[30m%s:%d, event=%s\x1b[0m\n", filename, line, event_str);
|
||||||
|
}
|
||||||
|
|
||||||
static char buf[2048];
|
static char buf[2048];
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
@ -55,15 +77,27 @@ int main(int argc, char** argv) {
|
|||||||
// signal(SIGINT, sigint_handler);
|
// signal(SIGINT, sigint_handler);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(argc > 2) {
|
bool trace = false;
|
||||||
printf("Usage: pocketpy [filename]\n");
|
const char* filename = NULL;
|
||||||
return 0;
|
|
||||||
|
for(int i = 1; i < argc; i++) {
|
||||||
|
if(strcmp(argv[i], "--trace") == 0) {
|
||||||
|
trace = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(filename == NULL) {
|
||||||
|
filename = argv[i];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("Usage: pocketpy [--trace] filename\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
py_initialize();
|
py_initialize();
|
||||||
py_sys_setargv(argc, argv);
|
py_sys_setargv(argc, argv);
|
||||||
|
|
||||||
if(argc == 1) {
|
if(trace) py_sys_settrace(tracefunc);
|
||||||
|
|
||||||
|
if(filename == NULL) {
|
||||||
printf("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") ");
|
printf("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") ");
|
||||||
printf("[%d bit] on %s", (int)(sizeof(void*) * 8), PY_SYS_PLATFORM_STRING);
|
printf("[%d bit] on %s", (int)(sizeof(void*) * 8), PY_SYS_PLATFORM_STRING);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@ -89,9 +123,9 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
char* source = read_file(argv[1]);
|
char* source = read_file(filename);
|
||||||
if(source) {
|
if(source) {
|
||||||
if(!py_exec(source, argv[1], EXEC_MODE, NULL)) py_printexc();
|
if(!py_exec(source, filename, EXEC_MODE, NULL)) py_printexc();
|
||||||
free(source);
|
free(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ class TestSuperBase():
|
|||||||
return self.base_attr
|
return self.base_attr
|
||||||
|
|
||||||
def error(self):
|
def error(self):
|
||||||
raise Exception('未能拦截错误')
|
raise RuntimeError('未能拦截错误')
|
||||||
|
|
||||||
|
|
||||||
class TestSuperChild1(TestSuperBase):
|
class TestSuperChild1(TestSuperBase):
|
||||||
@ -20,7 +20,7 @@ class TestSuperChild1(TestSuperBase):
|
|||||||
def error_handling(self):
|
def error_handling(self):
|
||||||
try:
|
try:
|
||||||
super(TestSuperChild1, self).error()
|
super(TestSuperChild1, self).error()
|
||||||
except:
|
except RuntimeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class TestSuperChild2(TestSuperBase):
|
class TestSuperChild2(TestSuperBase):
|
||||||
@ -54,18 +54,22 @@ class TestSuperNoBaseMethod(TestSuperBase):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(TestSuperNoBaseMethod, self).append(1)
|
super(TestSuperNoBaseMethod, self).append(1)
|
||||||
|
|
||||||
|
class TestSuperNoParent():
|
||||||
|
def method(self):
|
||||||
|
super(TestSuperNoParent, self).method()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
t = TestSuperNoParent()
|
t = TestSuperNoParent().method()
|
||||||
print('未能拦截错误')
|
print('未能拦截错误2')
|
||||||
exit(2)
|
exit(2)
|
||||||
except:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
t = TestSuperNoBaseMethod()
|
t = TestSuperNoBaseMethod()
|
||||||
print('未能拦截错误')
|
print('未能拦截错误3')
|
||||||
exit(3)
|
exit(3)
|
||||||
except:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class B():
|
class B():
|
||||||
@ -82,17 +86,17 @@ class D():
|
|||||||
try:
|
try:
|
||||||
c = C()
|
c = C()
|
||||||
c.method()
|
c.method()
|
||||||
print('未能拦截错误')
|
print('未能拦截错误4')
|
||||||
exit(4)
|
exit(4)
|
||||||
except:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
d = D()
|
d = D()
|
||||||
d.method()
|
d.method()
|
||||||
print('未能拦截错误')
|
print('未能拦截错误5')
|
||||||
exit(5)
|
exit(5)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# test hash:
|
# test hash:
|
||||||
@ -133,16 +137,16 @@ assert type(hash(a)) is int
|
|||||||
# 测试不可哈希对象
|
# 测试不可哈希对象
|
||||||
try:
|
try:
|
||||||
hash({1:1})
|
hash({1:1})
|
||||||
print('未能拦截错误')
|
print('未能拦截错误6')
|
||||||
exit(6)
|
exit(6)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hash([1])
|
hash([1])
|
||||||
print('未能拦截错误')
|
print('未能拦截错误7')
|
||||||
exit(7)
|
exit(7)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# test chr
|
# test chr
|
||||||
@ -165,24 +169,24 @@ repr(A())
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
range(1,2,3,4)
|
range(1,2,3,4)
|
||||||
print('未能拦截错误, 在测试 range')
|
print('未能拦截错误8, 在测试 range')
|
||||||
exit(8)
|
exit(8)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# /************ int ************/
|
# /************ int ************/
|
||||||
try:
|
try:
|
||||||
int('asad')
|
int('asad')
|
||||||
print('未能拦截错误, 在测试 int')
|
print('未能拦截错误9, 在测试 int')
|
||||||
exit(9)
|
exit(9)
|
||||||
except:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
int(123, 16)
|
int(123, 16)
|
||||||
print('未能拦截错误, 在测试 int')
|
print('未能拦截错误10, 在测试 int')
|
||||||
exit(10)
|
exit(10)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
assert type(10//11) is int
|
assert type(10//11) is int
|
||||||
@ -191,16 +195,16 @@ assert type(11%2) is int
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
float('asad')
|
float('asad')
|
||||||
print('未能拦截错误, 在测试 float')
|
print('未能拦截错误11, 在测试 float')
|
||||||
exit(11)
|
exit(11)
|
||||||
except:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
float([])
|
float([])
|
||||||
print('未能拦截错误, 在测试 float')
|
print('未能拦截错误12, 在测试 float')
|
||||||
exit(12)
|
exit(12)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# /************ str ************/
|
# /************ str ************/
|
||||||
@ -212,10 +216,10 @@ assert type(12 * '12') is str
|
|||||||
assert type('25363546'.index('63')) is int
|
assert type('25363546'.index('63')) is int
|
||||||
try:
|
try:
|
||||||
'25363546'.index('err')
|
'25363546'.index('err')
|
||||||
print('未能拦截错误, 在测试 str.index')
|
print('未能拦截错误13, 在测试 str.index')
|
||||||
exit(13)
|
exit(13)
|
||||||
except:
|
except ValueError as e:
|
||||||
pass
|
assert str(e) == "substring not found"
|
||||||
|
|
||||||
|
|
||||||
# 未完全测试准确性-----------------------------------------------
|
# 未完全测试准确性-----------------------------------------------
|
||||||
@ -227,9 +231,9 @@ assert '25363546'.find('err') == -1
|
|||||||
# /************ list ************/
|
# /************ list ************/
|
||||||
try:
|
try:
|
||||||
list(1,2)
|
list(1,2)
|
||||||
print('未能拦截错误, 在测试 list')
|
print('未能拦截错误14, 在测试 list')
|
||||||
exit(14)
|
exit(14)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 未完全测试准确性----------------------------------------------
|
# 未完全测试准确性----------------------------------------------
|
||||||
@ -237,10 +241,10 @@ except:
|
|||||||
assert type([1,2,3,4,5].index(4)) is int
|
assert type([1,2,3,4,5].index(4)) is int
|
||||||
try:
|
try:
|
||||||
[1,2,3,4,5].index(6)
|
[1,2,3,4,5].index(6)
|
||||||
print('未能拦截错误, 在测试 list.index')
|
print('未能拦截错误15, 在测试 list.index')
|
||||||
exit(15)
|
exit(15)
|
||||||
except:
|
except ValueError as e:
|
||||||
pass
|
assert str(e) == "list.index(x): x not in list"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -248,19 +252,19 @@ except:
|
|||||||
# test list.remove:
|
# test list.remove:
|
||||||
try:
|
try:
|
||||||
[1,2,3,4,5].remove(6)
|
[1,2,3,4,5].remove(6)
|
||||||
print('未能拦截错误, 在测试 list.remove')
|
print('未能拦截错误16, 在测试 list.remove')
|
||||||
exit(16)
|
exit(16)
|
||||||
except:
|
except ValueError as e:
|
||||||
pass
|
assert str(e) == "list.remove(x): x not in list"
|
||||||
|
|
||||||
|
|
||||||
# 未完全测试准确性----------------------------------------------
|
# 未完全测试准确性----------------------------------------------
|
||||||
# test list.pop:
|
# test list.pop:
|
||||||
try:
|
try:
|
||||||
[1,2,3,4,5].pop(1,2,3,4)
|
[1,2,3,4,5].pop(1,2,3,4)
|
||||||
print('未能拦截错误, 在测试 list.pop')
|
print('未能拦截错误17, 在测试 list.pop')
|
||||||
exit(17)
|
exit(17)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -274,9 +278,9 @@ assert type(12 * [12]) is list
|
|||||||
# test tuple:
|
# test tuple:
|
||||||
try:
|
try:
|
||||||
tuple(1,2)
|
tuple(1,2)
|
||||||
print('未能拦截错误, 在测试 tuple')
|
print('未能拦截错误18, 在测试 tuple')
|
||||||
exit(18)
|
exit(18)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
assert [1,2,2,3,3,3].count(3) == 3
|
assert [1,2,2,3,3,3].count(3) == 3
|
||||||
|
|||||||
@ -70,21 +70,21 @@ try:
|
|||||||
dict([(1, 2, 3)])
|
dict([(1, 2, 3)])
|
||||||
print('未能拦截错误, 在测试 dict')
|
print('未能拦截错误, 在测试 dict')
|
||||||
exit(1)
|
exit(1)
|
||||||
except:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dict([(1, 2)], 1)
|
dict([(1, 2)], 1)
|
||||||
print('未能拦截错误, 在测试 dict')
|
print('未能拦截错误, 在测试 dict')
|
||||||
exit(1)
|
exit(1)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hash(dict([(1,2)]))
|
hash(dict([(1,2)]))
|
||||||
print('未能拦截错误, 在测试 dict.__hash__')
|
print('未能拦截错误, 在测试 dict.__hash__')
|
||||||
exit(1)
|
exit(1)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# test dict.__iter__
|
# test dict.__iter__
|
||||||
@ -102,7 +102,7 @@ try:
|
|||||||
{1:2, 3:4}.get(1,1, 1)
|
{1:2, 3:4}.get(1,1, 1)
|
||||||
print('未能拦截错误, 在测试 dict.get')
|
print('未能拦截错误, 在测试 dict.get')
|
||||||
exit(1)
|
exit(1)
|
||||||
except:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# 未完全测试准确性-----------------------------------------------
|
# 未完全测试准确性-----------------------------------------------
|
||||||
|
|||||||
@ -52,13 +52,7 @@ assert A()[1:2, :A()[3:4, ::-1]] == (slice(1, 2, None), slice(None, (slice(3, 4,
|
|||||||
assert 2**2**3 == 256
|
assert 2**2**3 == 256
|
||||||
assert (2**2**3)**2 == 65536
|
assert (2**2**3)**2 == 65536
|
||||||
|
|
||||||
class Number:
|
class Number:
|
||||||
def __float__(self):
|
|
||||||
return 1.0
|
|
||||||
|
|
||||||
def __int__(self):
|
|
||||||
return 2
|
|
||||||
|
|
||||||
def __divmod__(self, other):
|
def __divmod__(self, other):
|
||||||
return 3, 4
|
return 3, 4
|
||||||
|
|
||||||
@ -66,9 +60,6 @@ class Number:
|
|||||||
return args
|
return args
|
||||||
|
|
||||||
assert divmod(Number(), 0) == (3, 4)
|
assert divmod(Number(), 0) == (3, 4)
|
||||||
assert float(Number()) == 1.0
|
|
||||||
assert int(Number()) == 2
|
|
||||||
|
|
||||||
assert round(Number()) == tuple()
|
assert round(Number()) == tuple()
|
||||||
assert round(Number(), 1) == (1,)
|
assert round(Number(), 1) == (1,)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user