Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@tell-k
Last active April 14, 2018 05:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tell-k/c7552ef551f06620e2f029f1495fe173 to your computer and use it in GitHub Desktop.
Save tell-k/c7552ef551f06620e2f029f1495fe173 to your computer and use it in GitHub Desktop.
ブロック内のコードをスキップできる + スコープを共有しない with statetment
# 1. ブロック内のコードを実行しない with -------
# refs http://stackoverflow.com/questions/12594148/skipping-execution-of-with-block
import sys
import inspect
class SkipContext:
def __enter__(self):
# 1. SkipContextの外側のframeを取得
self.frame, _, _, _, _, _ = inspect.getouterframes(inspect.currentframe())[1]
self.frame.f_trace = self.trace
sys.settrace(lambda *args, **keys: None) # 2. settraceを有効にする
def trace(self, frame, event, arg):
raise Exception('Skip with block') # 4. 3の行が実行される前にフックされて raiseされる
def __exit__(self, exec_type, exec_value, traceback):
# 5. 3の行は実行されずに、__exit__ にたどり着いて強制的にwithが終了
sys.settrace(None)
return True
with SkipContext():
print('Not execute this line.') # 3. この行が実行されようとする
# 2. スコープを共有しない with ------------
import inspect
import copy
class IsolatedScopeContext:
def __enter__(self):
self.frame, _, _, _, _, _ = inspect.getouterframes(inspect.currentframe())[1]
self.orig_globals = copy.copy(self.frame.f_globals) # 1. with に入る前の globalsを保存
def __exit__(self, exec_type, exec_value, traceback):
# 2. with を抜ける時に1で保存した globalsを復活
for k in list(self.frame.f_globals.keys()):
self.frame.f_globals.pop(k, None)
for k, v in self.orig_globals.items():
self.frame.f_globals[k] = v
return True
spam = 'spam'
with IsolatedScopeContext(): # withの抜けたあとに、この時点でのglobalsを復元する
spam = 'egg'
with IsolatedScopeContext():
print(spam) # => 'spam'
# 3 1 と 2を mix したやつ ------------------
import inspect
import sys
import copy
class SkipException(Exception):
pass
class SkippableContext:
def __init__(self, skip=False, isolated_scope=False):
self.skip = skip
self.isolated_scope = isolated_scope
def __enter__(self):
self.frame, _, _, _, _, _ = inspect.getouterframes(inspect.currentframe())[1]
if self.skip:
self.frame.f_trace = self.trace
sys.settrace(lambda *args, **keys: None)
if self.isolated_scope:
self.orig_globals = copy.copy(self.frame.f_globals)
def trace(self, frame, event, arg):
raise SkipException('Skip this context.')
def restore_globals(self):
for k in list(self.frame.f_globals.keys()):
self.frame.f_globals.pop(k, None)
for k, v in self.orig_globals.items():
self.frame.f_globals[k] = v
def __exit__(self, exec_type, exec_value, traceback):
sys.settrace(None)
if self.isolated_scope:
self.restore_globals()
if exec_type is SkipException:
return True
with SkippableContext():
print('Execute this line.')
with SkippableContext(skip=True):
print('Not Execute this line.')
var1 = 'var1'
with SkippableContext(isolated_scope=True):
var1 = 'update1'
print(var1)
with SkippableContext(isolated_scope=True):
print(var1)
var1 = 'update2'
print(var1) # => 'var1'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment