Skip to content

Commit

Permalink
fixed local dict in new version of code
Browse files Browse the repository at this point in the history
  • Loading branch information
joemarshall committed Mar 4, 2021
1 parent 11d1e99 commit 44e92e4
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 11 deletions.
10 changes: 9 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,13 @@
from Cython.Build import cythonize

setup(
ext_modules = cythonize("unthrow/*.pyx",build_dir="build")
name="unthrow",
version="0.1",
description="An exception that can be resumed. ",
author="Joe Marshall",
author_email="[email protected]",
url="https://github.com/joemarshall/unthrow",
py_modules=["unthrow"],

ext_modules = cythonize("unthrow/*.pyx")
)
1 change: 1 addition & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def mainApp():
print("L:",c)
if c==3 or c==5:
exceptionTest()
print("L2:",c)
print("END APP")

thisException=None
Expand Down
38 changes: 28 additions & 10 deletions unthrow/unthrow.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ import collections

import sys,inspect,dis

_SavedFrame=collections.namedtuple("_framestore",['locals_and_stack','lasti', 'code','block_stack'],module=__name__)
_SavedFrame=collections.namedtuple("_framestore",['locals_and_stack','lasti', 'code','block_stack','locals_map'],module=__name__)

class _PythonNULL(object):
pass

__skip_stop=False

cdef extern from "Python.h":

cdef int PyCompile_OpcodeStackEffectWithJump(int,int,int)
cdef char* PyBytes_AsString(PyObject *o)
cdef PyObject* PyBytes_FromStringAndSize(const char *v, Py_ssize_t len)
cdef Py_ssize_t PyObject_Length(PyObject *o)
cdef PyObject* PyDict_GetItem(PyObject*,PyObject*)

cdef extern from "frameobject.h":
ctypedef struct PyTryBlock:
Expand Down Expand Up @@ -50,20 +51,29 @@ cdef extern from "frameobject.h":
cdef void PyFrame_FastToLocals(PyFrameObject* frame)

cdef get_stack_pos_after(object code,int target):
cdef int no_jump
cdef int yes_jump
cdef int opcode
cdef int arg
stack_levels={}
jump_levels={}
cur_stack=0
for i in dis.get_instructions(code):
offset=i.offset
argval=i.argval
arg=i.arg
opcode=i.opcode
if i.arg:
arg=int(i.arg)
else:
arg=0
opcode=int(i.opcode)
if offset in jump_levels:
cur_stack=jump_levels[offset]
no_jump=dis.stack_effect(opcode,arg,jump=False)
no_jump=PyCompile_OpcodeStackEffectWithJump(opcode,arg,0)
#dis.stack_effect(opcode,arg,jump=False)
if opcode in dis.hasjabs or opcode in dis.hasjrel:
# a jump - mark the stack level at jump target
yes_jump=dis.stack_effect(opcode,arg,jump=True)
yes_jump=PyCompile_OpcodeStackEffectWithJump(opcode,arg,1)
# yes_jump=dis.stack_effect(opcode,arg,jump=True)
if not argval in jump_levels:
jump_levels[argval]=cur_stack+yes_jump
cur_stack+=no_jump
Expand All @@ -73,6 +83,8 @@ cdef get_stack_pos_after(object code,int target):


cdef object save_frame(PyFrameObject* source_frame):
cdef PyObject *localPtr;
PyFrame_FastToLocals(source_frame)
blockstack=[]
# last instruction called
lasti=source_frame.f_lasti
Expand All @@ -90,7 +102,10 @@ cdef object save_frame(PyFrameObject* source_frame):
blockstack=[]
for c in range(source_frame.f_iblock):
blockstack.append(source_frame.f_blockstack[c])
return _SavedFrame(locals_and_stack=valuestack,code=code_obj,lasti=lasti,block_stack=blockstack)
locals_map={}
if source_frame.f_locals!=source_frame.f_globals:
locals_map=(<object>source_frame).f_locals
return _SavedFrame(locals_and_stack=valuestack,code=code_obj,lasti=lasti,block_stack=blockstack,locals_map=locals_map)

cdef void restore_saved_frame(PyFrameObject* target_frame,saved_frame: _SavedFrame):
# last instruction
Expand All @@ -112,6 +127,9 @@ cdef void restore_saved_frame(PyFrameObject* target_frame,saved_frame: _SavedFra
for c,x in enumerate(saved_frame.block_stack):
target_frame.f_blockstack[c]=x
target_frame.f_iblock=len(saved_frame.block_stack)
# restore local symbols
target_frame.f_locals=<PyObject*>(saved_frame.locals_map)
Py_XINCREF(target_frame.f_locals)


class ResumableException(Exception):
Expand Down Expand Up @@ -147,7 +165,7 @@ class ResumableException(Exception):
if len(self.savedFrames)>0:
resumeFrame=self.savedFrames[-1]
if frame.f_code.co_code==resumeFrame.code:
print("MATCH FRAME:",frame,resumeFrame)
# print("MATCH FRAME:",frame,resumeFrame)
self.savedFrames=self.savedFrames[:-1]
restore_saved_frame(<PyFrameObject*>frame,resumeFrame)
if len(self.savedFrames)==0:
Expand All @@ -157,10 +175,10 @@ class ResumableException(Exception):
def stop(msg):
global __skip_stop
if __skip_stop:
print("RESUMING")
# print("RESUMING")
__skip_stop=False
else:
print("STOPPING NOW")
# print("STOPPING NOW")
rex=ResumableException(msg)
raise rex

Expand Down

0 comments on commit 44e92e4

Please sign in to comment.