Skip to content

Commit

Permalink
revert idle
Browse files Browse the repository at this point in the history
  • Loading branch information
archibate committed Jun 23, 2020
1 parent 411af8b commit 794bf05
Show file tree
Hide file tree
Showing 5 changed files with 4 additions and 207 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ __pycache__
*.ini
*.egg-info
.tlang_cache
.tmp_idle_*
/taichi/common/version.h
/taichi/common/commit_hash.h
/python/test_env
Expand Down
41 changes: 0 additions & 41 deletions python/taichi/idle_hacker.py

This file was deleted.

2 changes: 0 additions & 2 deletions python/taichi/lang/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,6 @@ def reset():
for k in old_kernels:
k.reset()
taichi_lang_core.reset_default_compile_config()
from .shell import reset_callback
reset_callback()


def inside_kernel():
Expand Down
151 changes: 0 additions & 151 deletions python/taichi/lang/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,11 @@

class ShellType:
NATIVE = 'Python shell'
IDLE = 'Python IDLE shell'
IPYTHON = 'IPython TerminalInteractiveShell'
JUPYTER = 'IPython ZMQInteractiveShell'
IPYBASED = 'IPython Based Shell'
SCRIPT = None

def _show_idle_error_message():
import code
try:
path = code.__file__
except:
path = '/usr/lib/python3.8/code.py'
print('It\'s detected that you are using Python IDLE in **interactive mode**.')
print('However, Taichi could not be fully functional due to IDLE limitation, sorry :(')
print('Either run Taichi directly from script, or use IPython notebook instead.')
print('We do care about your experience, no matter which shell you prefer to use.')
print('So, if you would like to play with Taichi in your favorite IDLE, we may do a dirty hack:')
print(f'Open "{path}" and add the following line to `InteractiveInterpreter.runsource`, right below `# Case 3`:')
print('''
class InteractiveInterpreter:
...
def runsource(self, source, filename="<input>", symbol="single"):
...
# Case 3
(lambda o,k:o.path.exists(k+'ppid_'+str(o.getpid()))and(lambda f:(f.write(f'\\n===\\n'+source),f.close()))(open(k+'source','a')))(__import__('os'),'.tmp_idle_') # Add this line!
self.runcode(code)
return False
...
''')
print('If you don\'t find where to add, we provided a script to automatically inject the code:')
print(' sudo python3 -m taichi idle_hacker')
print('')
print('Then, restart IDLE and enjoy, the sky is blue and we are wizards!')


def get_shell_name():
"""
Expand Down Expand Up @@ -69,31 +36,6 @@ def get_shell_name():
if hasattr(__builtins__, '__IPYTHON__'):
return ShellType.IPYBASED

if os.path.basename(sys.executable) == 'pythonw.exe': # Windows Python IDLE?
return ShellType.IDLE

if os.path.basename(os.environ.get('_', '')) == 'idle': # /usr/bin/idle?
return ShellType.IDLE

try:
import psutil
# XXX: Is psutil a hard dep of taichi? What if user didn't install it?
proc = psutil.Process().parent()
if proc.name() == 'idle': # launched from KDE win menu?
return ShellType.IDLE
cmdline = proc.cmdline()
# launched with: python -m idlelib?
if 'idlelib' in cmdline:
return ShellType.IDLE
# sh-bomb: /usr/bin/python /usr/bin/idle?
if len(cmdline) >= 2 and os.path.basename(cmdline[1]) == 'idle':
return ShellType.IDLE
except:
pass

if 'idlelib' in sys.modules:
return ShellType.IDLE

try:
if getattr(sys, 'ps1', sys.flags.interactive):
return ShellType.NATIVE
Expand Down Expand Up @@ -130,71 +72,6 @@ def __init__(self):
self.getsourcelines = dill.source.getsourcelines
self.getsourcefile = dill.source.getsourcefile

elif self.name == ShellType.IDLE:
# `.tmp_idle_source` for "Python IDLE shell"
# Thanks to IDLE's lack of support with `inspect`,
# we have to use a dirty hack to support Taichi there.
self.idle_cache = {}

ppid_file = '.tmp_idle_ppid_' + str(os.getppid())
with open(ppid_file, 'w') as f:
import taichi as ti
ti.info(f'[Taichi] touching {ppid_file}')
f.write('taichi')

def getsource(o):
func_name = o.__name__
if func_name in self.idle_cache:
return self.idle_cache[func_name]
src = None
try:
with open('.tmp_idle_source') as f:
src = f.read()
except FileNotFoundError as e:
_show_idle_error_message()
raise e

# If user added our 'hacker-code' correctly,
# then the content of .tmp_idle_source should be:
#
# ===
# import taichi as ti
#
# ===
# @ti.kernel
# def func(): # x.find('def ') locate to here
# pass
#
# ===
# func()
#
#
# Thanking IDLE dev :( It works anyway :)
for x in src.split('==='):
x = x.strip()
i = x.find('def ')
if i == -1:
continue
name = x[i + 4:].split(':', maxsplit=1)[0]
name = name.split('(', maxsplit=1)[0]
if name.strip() == func_name:
self.idle_cache[func_name] = x
return x
else:
raise NameError(f'Could not find source for {o.__name__}!')

def getsourcelines(o):
lineno = 2 # TODO: consider include lineno in .tmp_idle_source?
lines = getsource(o).split('\n')
return lines, lineno

def getsourcefile(o):
return '<IDLE>'

self.getsource = getsource
self.getsourcelines = getsourcelines
self.getsourcefile = getsourcefile

elif self.name.startswith('IPython'):
# `IPython.core.oinspect` for "IPython advanced shell"
def getsource(o):
Expand All @@ -219,31 +96,3 @@ def getsourcefile(o):


oinspect = None

def _try_clean(filename):
try:
os.unlink(filename)
except:
pass
else:
import taichi as ti
ti.info('File ".tmp_idle_source" cleaned')

def reset_callback():
global oinspect
oinspect = ShellInspectorWrapper()

def is_idle_oinspect():
return isinstance(oinspect, ShellInspectorWrapper) and \
oinspect.name == ShellType.IDLE

if is_idle_oinspect():
_try_clean('.tmp_idle_source')

def exit_callback():
if is_idle_oinspect():
_try_clean('.tmp_idle_source')
_try_clean('.tmp_idle_ppid_' + os.getppid())
atexit.register(exit_callback)

reset_callback()
16 changes: 4 additions & 12 deletions python/taichi/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -899,21 +899,13 @@ def debug(self, arguments: list = sys.argv[2:]):
# Short circuit for testing
if self.test_mode: return args

os.environ['TI_DEBUG'] = '1'
os.environ['TI_LOG_LEVEL'] = 'debug'
ti.core.set_core_trigger_gdb_when_crash(True)

runpy.run_path(args.filename, run_name='__main__')
with open(args.filename) as script:
script = script.read()

@register
def idle_hacker(self, arguments: list = sys.argv[2:]):
"""Run idle hack code injector"""
parser = argparse.ArgumentParser(prog='ti idle_hacker',
description=f"{self.idle_hacker.__doc__}")
args = parser.parse_args(arguments)

from .idle_hacker import main
return main()
# FIXME: exec is a security risk here!
exec(script, {'__name__': '__main__'})

@register
def run(self, arguments: list = sys.argv[2:]):
Expand Down

0 comments on commit 794bf05

Please sign in to comment.