##// END OF EJS Templates
Finished initial reworking and updating of setup.py and friends, including the MANIFEST.in. Everything seems...
Finished initial reworking and updating of setup.py and friends, including the MANIFEST.in. Everything seems to work fine. I have also gone through the tests in various subpackages (like kernel) and have protected imports of twisted, zope.interface and foolscap with a try/except clause. Now the tests are simply not run if these deps are missing. All tests now pass no matter what.

File last commit:

r1234:52b55407
r1244:ba669b1a
Show More
contexts.py
178 lines | 5.5 KiB | text/x-python | PythonLexer
Brian E Granger
This is a manual merge of certain things in the ipython1-dev branch, revision 46, into the main ...
r1234 # encoding: utf-8
# -*- test-case-name: IPython.kernel.test.test_contexts -*-
"""Context managers for IPython.
Python 2.5 introduced the `with` statement, which is based on the context
manager protocol. This module offers a few context managers for common cases,
which can also be useful as templates for writing new, application-specific
managers.
"""
from __future__ import with_statement
__docformat__ = "restructuredtext en"
#-------------------------------------------------------------------------------
# Copyright (C) 2008 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# Imports
#-------------------------------------------------------------------------------
import linecache
import sys
from twisted.internet.error import ConnectionRefusedError
from IPython.ultraTB import _fixed_getinnerframes, findsource
from IPython import ipapi
from IPython.kernel import error
#---------------------------------------------------------------------------
# Utility functions needed by all context managers.
#---------------------------------------------------------------------------
def remote():
"""Raises a special exception meant to be caught by context managers.
"""
m = 'Special exception to stop local execution of parallel code.'
raise error.StopLocalExecution(m)
def strip_whitespace(source,require_remote=True):
"""strip leading whitespace from input source.
:Parameters:
"""
remote_mark = 'remote()'
# Expand tabs to avoid any confusion.
wsource = [l.expandtabs(4) for l in source]
# Detect the indentation level
done = False
for line in wsource:
if line.isspace():
continue
for col,char in enumerate(line):
if char != ' ':
done = True
break
if done:
break
# Now we know how much leading space there is in the code. Next, we
# extract up to the first line that has less indentation.
# WARNINGS: we skip comments that may be misindented, but we do NOT yet
# detect triple quoted strings that may have flush left text.
for lno,line in enumerate(wsource):
lead = line[:col]
if lead.isspace():
continue
else:
if not lead.lstrip().startswith('#'):
break
# The real 'with' source is up to lno
src_lines = [l[col:] for l in wsource[:lno+1]]
# Finally, check that the source's first non-comment line begins with the
# special call 'remote()'
if require_remote:
for nline,line in enumerate(src_lines):
if line.isspace() or line.startswith('#'):
continue
if line.startswith(remote_mark):
break
else:
raise ValueError('%s call missing at the start of code' %
remote_mark)
out_lines = src_lines[nline+1:]
else:
# If the user specified that the remote() call wasn't mandatory
out_lines = src_lines
# src = ''.join(out_lines) # dbg
#print 'SRC:\n<<<<<<<>>>>>>>\n%s<<<<<>>>>>>' % src # dbg
return ''.join(out_lines)
class RemoteContextBase(object):
def __init__(self):
self.ip = ipapi.get()
def _findsource_file(self,f):
linecache.checkcache()
s = findsource(f.f_code)
lnum = f.f_lineno
wsource = s[0][f.f_lineno:]
return strip_whitespace(wsource)
def _findsource_ipython(self,f):
from IPython import ipapi
self.ip = ipapi.get()
buf = self.ip.IP.input_hist_raw[-1].splitlines()[1:]
wsource = [l+'\n' for l in buf ]
return strip_whitespace(wsource)
def findsource(self,frame):
local_ns = frame.f_locals
global_ns = frame.f_globals
if frame.f_code.co_filename == '<ipython console>':
src = self._findsource_ipython(frame)
else:
src = self._findsource_file(frame)
return src
def __enter__(self):
raise NotImplementedError
def __exit__ (self, etype, value, tb):
if issubclass(etype,error.StopLocalExecution):
return True
class RemoteMultiEngine(RemoteContextBase):
def __init__(self,mec):
self.mec = mec
RemoteContextBase.__init__(self)
def __enter__(self):
src = self.findsource(sys._getframe(1))
return self.mec.execute(src)
# XXX - Temporary hackish testing, we'll move this into proper tests right
# away
if __name__ == '__main__':
# XXX - for now, we need a running cluster to be started separately. The
# daemon work is almost finished, and will make much of this unnecessary.
from IPython.kernel import client
mec = client.MultiEngineClient(('127.0.0.1',10105))
try:
mec.get_ids()
except ConnectionRefusedError:
import os, time
os.system('ipcluster -n 2 &')
time.sleep(2)
mec = client.MultiEngineClient(('127.0.0.1',10105))
mec.block = False
import itertools
c = itertools.count()
parallel = RemoteMultiEngine(mec)
with parallel as pr:
# A comment
remote() # this means the code below only runs remotely
print 'Hello remote world'
x = 3.14
# Comments are OK
# Even misindented.
y = x+1