yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #08098
[SCM] Yet Another Dynamic Engine. Platform for discrete element modeling. branch, master, updated. upstream/0.70.0-109-g22291a8
The following commit has been merged in the master branch:
commit 6c190370c1f08ad0eb5ed3b416e4eacf909267a3
Author: Anton Gladky <gladky.anton@xxxxxxxxx>
Date: Fri Nov 25 20:26:56 2011 +0100
Provide ipython-0.11 compatibility. (Closes: #636475)
diff --git a/debian/copyright b/debian/copyright
index d8fb9a2..3d63b5a 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,4 +1,4 @@
-Format: http://dep.debian.net/deps/dep5/
+iFormat: http://dep.debian.net/deps/dep5/
Source: https://launchpad.net/yade
Files: *
@@ -225,3 +225,31 @@ License: CeCILL (open-source GPL compatible)
.
The full text of the License can be obtained on the web-page
http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+
+Files: doc/sphinx/ipython*.py
+Copyright: 2008-2010 IPython Development Team
+License: Modified BSD License
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ .
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ .
+ Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+ .
+ Neither the name of the IPython Development Team nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/debian/patches/ipython-0.11-migration.patch b/debian/patches/ipython-0.11-migration.patch
new file mode 100644
index 0000000..09cfadf
--- /dev/null
+++ b/debian/patches/ipython-0.11-migration.patch
@@ -0,0 +1,860 @@
+--- a/core/main/main.py.in
++++ b/core/main/main.py.in
+@@ -218,7 +218,7 @@
+ import IPython.ipapi
+ IPython.ipapi.get().IP.atexit_operations()
+ elif yade.runtime.ipython_version==11:
+- from IPython.core.embed import InteractiveShellEmbed
++ from IPython.frontend.terminal.embed import InteractiveShellEmbed
+ # use the dict to set attributes
+ for k in ipconfig: setattr(InteractiveShellEmbed,k,ipconfig[k])
+ InteractiveShellEmbed.banner1=banner # called banner1 here, not banner anymore
+@@ -263,5 +263,5 @@
+ qapp=QtGui.QApplication(sys.argv)
+ userSession(qt4=True,qapp=qapp)
+
+-O.exitNoBacktrace()
++#O.exitNoBacktrace()
+
+--- a/doc/sphinx/conf.py
++++ b/doc/sphinx/conf.py
+@@ -366,7 +366,7 @@
+ id.fmtout =' -> [%d]: ' # for some reason, out and cont must have the trailing space
+ id.fmtcont=' .\D.: '
+ id.rc_override=dict(prompt_in1="Yade [\#]:",prompt_in2=" .\D.:",prompt_out=r" -> [\#]: ")
+- id.reconfig_shell()
++ #id.reconfig_shell()
+
+ import ipython_console_highlighting as ich
+ ich.IPythonConsoleLexer.input_prompt = re.compile("(Yade \[[0-9]+\]: )")
+--- a/doc/sphinx/ipython_console_highlighting.py
++++ b/doc/sphinx/ipython_console_highlighting.py
+@@ -13,7 +13,7 @@
+
+ # Third party
+ from pygments.lexer import Lexer, do_insertions
+-from pygments.lexers.agile import (PythonConsoleLexer, PythonLexer,
++from pygments.lexers.agile import (PythonConsoleLexer, PythonLexer,
+ PythonTracebackLexer)
+ from pygments.token import Comment, Generic
+
+@@ -48,7 +48,7 @@
+
+ - It assumes the default IPython prompts, not customized ones.
+ """
+-
++
+ name = 'IPython console session'
+ aliases = ['ipython']
+ mimetypes = ['text/x-ipython-console']
+--- a/doc/sphinx/ipython_directive.py
++++ b/doc/sphinx/ipython_directive.py
+@@ -3,37 +3,38 @@
+
+ This directive allows pasting of entire interactive IPython sessions, prompts
+ and all, and their code will actually get re-executed at doc build time, with
+-all prompts renumbered sequentially.
++all prompts renumbered sequentially. It also allows you to input code as a pure
++python input by giving the argument python to the directive. The output looks
++like an interactive ipython section.
+
+ To enable this directive, simply list it in your Sphinx ``conf.py`` file
+ (making sure the directory where you placed it is visible to sphinx, as is
+ needed for all Sphinx directives).
+
+ By default this directive assumes that your prompts are unchanged IPython ones,
+-but this can be customized. For example, the following code in your Sphinx
+-config file will configure this directive for the following input/output
+-prompts ``Yade [1]:`` and ``-> [1]:``::
+-
+- import ipython_directive as id
+- id.rgxin =re.compile(r'(?:In |Yade )\[(\d+)\]:\s?(.*)\s*')
+- id.rgxout=re.compile(r'(?:Out| -> )\[(\d+)\]:\s?(.*)\s*')
+- id.fmtin ='Yade [%d]:'
+- id.fmtout=' -> [%d]:'
+-
+- id.rc_override=dict(
+- prompt_in1="Yade [\#]:",
+- prompt_in2=" .\D..",
+- prompt_out=" -> [\#]:"
+- )
+- id.reconfig_shell()
+-
+- import ipython_console_highlighting as ich
+- ich.IPythonConsoleLexer.input_prompt=
+- re.compile("(Yade \[[0-9]+\]: )|( \.\.\.+:)")
+- ich.IPythonConsoleLexer.output_prompt=
+- re.compile("(( -> )|(Out)\[[0-9]+\]: )|( \.\.\.+:)")
+- ich.IPythonConsoleLexer.continue_prompt=re.compile(" \.\.\.+:")
++but this can be customized. The configurable options that can be placed in
++conf.py are
+
++ipython_savefig_dir:
++ The directory in which to save the figures. This is relative to the
++ Sphinx source directory. The default is `html_static_path`.
++ipython_rgxin:
++ The compiled regular expression to denote the start of IPython input
++ lines. The default is re.compile('In \[(\d+)\]:\s?(.*)\s*'). You
++ shouldn't need to change this.
++ipython_rgxout:
++ The compiled regular expression to denote the start of IPython output
++ lines. The default is re.compile('Out\[(\d+)\]:\s?(.*)\s*'). You
++ shouldn't need to change this.
++ipython_promptin:
++ The string to represent the IPython input prompt in the generated ReST.
++ The default is 'In [%d]:'. This expects that the line numbers are used
++ in the prompt.
++ipython_promptout:
++
++ The string to represent the IPython prompt in the generated ReST. The
++ default is 'Out [%d]:'. This expects that the line numbers are used
++ in the prompt.
+
+ ToDo
+ ----
+@@ -41,15 +42,14 @@
+ - Turn the ad-hoc test() function into a real test suite.
+ - Break up ipython-specific functionality from matplotlib stuff into better
+ separated code.
+-- Make sure %bookmarks used internally are removed on exit.
+-
+
+ Authors
+ -------
+
+ - John D Hunter: orignal author.
+-- Fernando Perez: refactoring, documentation, cleanups.
+-- VáclavŠmilauer <eudoxos-AT-arcig.cz>: Prompt generatlizations.
++- Fernando Perez: refactoring, documentation, cleanups, port to 0.11.
++- VáclavŠmilauer <eudoxos-AT-arcig.cz>: Prompt generalizations.
++- Skipper Seabold, refactoring, cleanups, pure python addition
+ """
+
+ #-----------------------------------------------------------------------------
+@@ -58,12 +58,10 @@
+
+ # Stdlib
+ import cStringIO
+-import imp
+ import os
+ import re
+-import shutil
+ import sys
+-import warnings
++import tempfile
+
+ # To keep compatibility with various python versions
+ try:
+@@ -75,36 +73,26 @@
+ import matplotlib
+ import sphinx
+ from docutils.parsers.rst import directives
++from docutils import nodes
++from sphinx.util.compat import Directive
+
+ matplotlib.use('Agg')
+
+ # Our own
+-import IPython
+-from IPython.Shell import MatplotlibShell
++from IPython import Config, InteractiveShell
++from IPython.core.profiledir import ProfileDir
++from IPython.utils import io
+
+ #-----------------------------------------------------------------------------
+ # Globals
+ #-----------------------------------------------------------------------------
+-
+-sphinx_version = sphinx.__version__.split(".")
+-# The split is necessary for sphinx beta versions where the string is
+-# '6b1'
+-sphinx_version = tuple([int(re.split('[a-z]', x)[0])
+- for x in sphinx_version[:2]])
+-
++# for tokenizing blocks
+ COMMENT, INPUT, OUTPUT = range(3)
+-rc_override = {}
+-rgxin = re.compile('In \[(\d+)\]:\s?(.*)\s*')
+-rgxcont = re.compile(' \.+:\s?(.*)\s*')
+-rgxout = re.compile('Out\[(\d+)\]:\s?(.*)\s*')
+-fmtin = 'In [%d]:'
+-fmtout = 'Out[%d]:'
+-fmtcont = ' .\D.:'
+
+ #-----------------------------------------------------------------------------
+ # Functions and class declarations
+ #-----------------------------------------------------------------------------
+-def block_parser(part):
++def block_parser(part, rgxin, rgxout, fmtin, fmtout):
+ """
+ part is a string of ipython text, comprised of at most one
+ input, one ouput, comments, and blank lines. The block parser
+@@ -156,8 +144,8 @@
+ lineno, inputline = int(matchin.group(1)), matchin.group(2)
+
+ # the ....: continuation string
+- #continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
+- #Nc = len(continuation)
++ continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
++ Nc = len(continuation)
+ # input lines can continue on for more than one line, if
+ # we have a '\' line continuation char or a function call
+ # echo line 'print'. The input line can only be
+@@ -173,12 +161,11 @@
+
+ nextline = lines[i]
+ matchout = rgxout.match(nextline)
+- matchcont = rgxcont.match(nextline)
+ #print "nextline=%s, continuation=%s, starts=%s"%(nextline, continuation, nextline.startswith(continuation))
+ if matchout or nextline.startswith('#'):
+ break
+- elif matchcont: #nextline.startswith(continuation):
+- inputline += '\n' + matchcont.group(1) #nextline[Nc:]
++ elif nextline.startswith(continuation):
++ inputline += '\n' + nextline[Nc:]
+ else:
+ rest.append(nextline)
+ i+= 1
+@@ -199,7 +186,6 @@
+
+ return block
+
+-
+ class EmbeddedSphinxShell(object):
+ """An embedded IPython instance to run inside Sphinx"""
+
+@@ -207,17 +193,38 @@
+
+ self.cout = cStringIO.StringIO()
+
+- IPython.Shell.Term.cout = self.cout
+- IPython.Shell.Term.cerr = self.cout
+- argv = ['-autocall', '0']
+- self.user_ns = {}
+- self.user_glocal_ns = {}
+-
+- self.IP = IPython.ipmaker.make_IPython(
+- argv, self.user_ns, self.user_glocal_ns, embedded=True,
+- #shell_class=IPython.Shell.InteractiveShell,
+- shell_class=MatplotlibShell,
+- rc_override = dict(colors = 'NoColor', **rc_override))
++
++ # Create config object for IPython
++ config = Config()
++ config.Global.display_banner = False
++ config.Global.exec_lines = ['import numpy as np',
++ 'from pylab import *'
++ ]
++ config.InteractiveShell.autocall = False
++ config.InteractiveShell.autoindent = False
++ config.InteractiveShell.colors = 'NoColor'
++
++ # create a profile so instance history isn't saved
++ tmp_profile_dir = tempfile.mkdtemp(prefix='profile_')
++ profname = 'auto_profile_sphinx_build'
++ pdir = os.path.join(tmp_profile_dir,profname)
++ profile = ProfileDir.create_profile_dir(pdir)
++
++ # Create and initialize ipython, but don't start its mainloop
++ IP = InteractiveShell.instance(config=config, profile_dir=profile)
++ # io.stdout redirect must be done *after* instantiating InteractiveShell
++ io.stdout = self.cout
++ io.stderr = self.cout
++
++ # For debugging, so we can see normal output, use this:
++ #from IPython.utils.io import Tee
++ #io.stdout = Tee(self.cout, channel='stdout') # dbg
++ #io.stderr = Tee(self.cout, channel='stderr') # dbg
++
++ # Store a few parts of IPython we'll need.
++ self.IP = IP
++ self.user_ns = self.IP.user_ns
++ self.user_global_ns = self.IP.user_global_ns
+
+ self.input = ''
+ self.output = ''
+@@ -230,28 +237,62 @@
+ # pyplot as plt so we can make a call to the plt.gcf().savefig
+ self._pyplot_imported = False
+
+- # we need bookmark the current dir first so we can save
+- # relative to it
+- self.process_input_line('bookmark ipy_basedir')
++ def clear_cout(self):
+ self.cout.seek(0)
+ self.cout.truncate(0)
+
+- def process_input_line(self, line):
++ def process_input_line(self, line, store_history=True):
+ """process the input, capturing stdout"""
+ #print "input='%s'"%self.input
+ stdout = sys.stdout
+- sys.stdout = self.cout
+- #self.IP.resetbuffer()
+- self.IP.push(self.IP.prefilter(line, 0))
+- #self.IP.runlines(line)
+- sys.stdout = stdout
++ splitter = self.IP.input_splitter
++ try:
++ sys.stdout = self.cout
++ splitter.push(line)
++ more = splitter.push_accepts_more()
++ if not more:
++ source_raw = splitter.source_raw_reset()[1]
++ self.IP.run_cell(source_raw, store_history=store_history)
++ finally:
++ sys.stdout = stdout
++
++ def process_image(self, decorator):
++ """
++ # build out an image directive like
++ # .. image:: somefile.png
++ # :width 4in
++ #
++ # from an input like
++ # savefig somefile.png width=4in
++ """
++ savefig_dir = self.savefig_dir
++ source_dir = self.source_dir
++ saveargs = decorator.split(' ')
++ filename = saveargs[1]
++ # insert relative path to image file in source
++ outfile = os.path.relpath(os.path.join(savefig_dir,filename),
++ source_dir)
++
++ imagerows = ['.. image:: %s'%outfile]
++
++ for kwarg in saveargs[2:]:
++ arg, val = kwarg.split('=')
++ arg = arg.strip()
++ val = val.strip()
++ imagerows.append(' :%s: %s'%(arg, val))
++
++ image_file = os.path.basename(outfile) # only return file name
++ image_directive = '\n'.join(imagerows)
++ return image_file, image_directive
++
+
+ # Callbacks for each type of token
+ def process_input(self, data, input_prompt, lineno):
+ """Process data block for INPUT token."""
+ decorator, input, rest = data
+ image_file = None
+- #print 'INPUT:', data
++ image_directive = None
++ #print 'INPUT:', data # dbg
+ is_verbatim = decorator=='@verbatim' or self.is_verbatim
+ is_doctest = decorator=='@doctest' or self.is_doctest
+ is_suppress = decorator=='@suppress' or self.is_suppress
+@@ -260,54 +301,37 @@
+
+ input_lines = input.split('\n')
+
+- #continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
+- #Nc = len(continuation)
++ continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
++ Nc = len(continuation)
+
+ if is_savefig:
+- saveargs = decorator.split(' ')
+- filename = saveargs[1]
+- outfile = os.path.join('_static/%s'%filename)
+- # build out an image directive like
+- # .. image:: somefile.png
+- # :width 4in
+- #
+- # from an input like
+- # savefig somefile.png width=4in
+- imagerows = ['.. image:: %s'%outfile]
+-
+- for kwarg in saveargs[2:]:
+- arg, val = kwarg.split('=')
+- arg = arg.strip()
+- val = val.strip()
+- imagerows.append(' :%s: %s'%(arg, val))
+-
+- image_file = outfile
+- image_directive = '\n'.join(imagerows)
+-
+- # TODO: can we get "rest" from ipython
+- #self.process_input_line('\n'.join(input_lines))
++ image_file, image_directive = self.process_image(decorator)
+
+ ret = []
+ is_semicolon = False
++ store_history = True
+
+ for i, line in enumerate(input_lines):
+ if line.endswith(';'):
+ is_semicolon = True
++ if is_semicolon or is_suppress:
++ store_history = False
+
+ if i==0:
+ # process the first input line
+ if is_verbatim:
+ self.process_input_line('')
++ self.IP.execution_count += 1 # increment it anyway
+ else:
+ # only submit the line in non-verbatim mode
+- self.process_input_line(line)
++ self.process_input_line(line, store_history=store_history)
+ formatted_line = '%s %s'%(input_prompt, line)
+ else:
+ # process a continuation line
+ if not is_verbatim:
+- self.process_input_line(line)
++ self.process_input_line(line, store_history=store_history)
+
+- formatted_line = fmtcont.replace('\D','.'*len(str(lineno)))+line #'%s %s'%(continuation, line)
++ formatted_line = '%s %s'%(continuation, line)
+
+ if not is_suppress:
+ ret.append(formatted_line)
+@@ -326,7 +350,8 @@
+ ret.append(output)
+
+ self.cout.truncate(0)
+- return ret, input_lines, output, is_doctest, image_file
++ return (ret, input_lines, output, is_doctest, image_file,
++ image_directive)
+ #print 'OUTPUT', output # dbg
+
+ def process_output(self, data, output_prompt,
+@@ -336,46 +361,68 @@
+ submitted = data.strip()
+ found = output
+ if found is not None:
++ found = found.strip()
++
++ # XXX - fperez: in 0.11, 'output' never comes with the prompt
++ # in it, just the actual output text. So I think all this code
++ # can be nuked...
++
++ # the above comment does not appear to be accurate... (minrk)
++
+ ind = found.find(output_prompt)
+ if ind<0:
+- raise RuntimeError('output prompt="%s" does not match out line=%s'%(output_prompt, found))
++ e='output prompt="%s" does not match out line=%s' % \
++ (output_prompt, found)
++ raise RuntimeError(e)
+ found = found[len(output_prompt):].strip()
+
+ if found!=submitted:
+- raise RuntimeError('doctest failure for input_lines="%s" with found_output="%s" and submitted output="%s"'%(input_lines, found, submitted))
++ e = ('doctest failure for input_lines="%s" with '
++ 'found_output="%s" and submitted output="%s"' %
++ (input_lines, found, submitted) )
++ raise RuntimeError(e)
+ #print 'doctest PASSED for input_lines="%s" with found_output="%s" and submitted output="%s"'%(input_lines, found, submitted)
+
+ def process_comment(self, data):
+- """Process data block for COMMENT token."""
++ """Process data fPblock for COMMENT token."""
+ if not self.is_suppress:
+ return [data]
+
++ def save_image(self, image_file):
++ """
++ Saves the image file to disk.
++ """
++ self.ensure_pyplot()
++ command = 'plt.gcf().savefig("%s")'%image_file
++ #print 'SAVEFIG', command # dbg
++ self.process_input_line('bookmark ipy_thisdir', store_history=False)
++ self.process_input_line('cd -b ipy_savedir', store_history=False)
++ self.process_input_line(command, store_history=False)
++ self.process_input_line('cd -b ipy_thisdir', store_history=False)
++ self.process_input_line('bookmark -d ipy_thisdir', store_history=False)
++ self.clear_cout()
++
++
+ def process_block(self, block):
+ """
+ process block from the block_parser and return a list of processed lines
+ """
+-
+ ret = []
+ output = None
+ input_lines = None
++ lineno = self.IP.execution_count
+
+- m = rgxin.match(str(self.IP.outputcache.prompt1).strip())
+- lineno = int(m.group(1))
+-
+- input_prompt = fmtin%lineno
+- output_prompt = fmtout%lineno
++ input_prompt = self.promptin%lineno
++ output_prompt = self.promptout%lineno
+ image_file = None
+ image_directive = None
+- # XXX - This needs a second refactor. There's too much state being
+- # held globally, which makes for a very awkward interface and large,
+- # hard to test functions. I've already broken this up at least into
+- # three separate processors to isolate the logic better, but this only
+- # serves to highlight the coupling. Next we need to clean it up...
++
+ for token, data in block:
+ if token==COMMENT:
+ out_data = self.process_comment(data)
+ elif token==INPUT:
+- out_data, input_lines, output, is_doctest, image_file= \
++ (out_data, input_lines, output, is_doctest, image_file,
++ image_directive) = \
+ self.process_input(data, input_prompt, lineno)
+ elif token==OUTPUT:
+ out_data = \
+@@ -385,87 +432,235 @@
+ if out_data:
+ ret.extend(out_data)
+
++ # save the image files
+ if image_file is not None:
+- self.ensure_pyplot()
+- command = 'plt.gcf().savefig("%s")'%image_file
+- #print 'SAVEFIG', command # dbg
+- self.process_input_line('bookmark ipy_thisdir')
+- self.process_input_line('cd -b ipy_basedir')
+- self.process_input_line(command)
+- self.process_input_line('cd -b ipy_thisdir')
+- self.cout.seek(0)
+- self.cout.truncate(0)
++ self.save_image(image_file)
++
+ return ret, image_directive
+
+ def ensure_pyplot(self):
+ if self._pyplot_imported:
+ return
+- self.process_input_line('import matplotlib.pyplot as plt')
++ self.process_input_line('import matplotlib.pyplot as plt',
++ store_history=False)
+
+-# A global instance used below. XXX: not sure why this can't be created inside
+-# ipython_directive itself.
+-shell = EmbeddedSphinxShell()
+-
+-def reconfig_shell():
+- """Called after setting module-level variables to re-instantiate
+- with the set values (since shell is instantiated first at import-time
+- when module variables have default values)"""
+- global shell
+- shell = EmbeddedSphinxShell()
++ def process_pure_python(self, content):
++ """
++ content is a list of strings. it is unedited directive conent
+
++ This runs it line by line in the InteractiveShell, prepends
++ prompts as needed capturing stderr and stdout, then returns
++ the content as a list as if it were ipython code
++ """
++ output = []
++ savefig = False # keep up with this to clear figure
++ multiline = False # to handle line continuation
++ fmtin = self.promptin
++
++ for lineno, line in enumerate(content):
++
++ line_stripped = line.strip()
++
++ if not len(line):
++ output.append(line) # preserve empty lines in output
++ continue
++
++ # handle decorators
++ if line_stripped.startswith('@'):
++ output.extend([line])
++ if 'savefig' in line:
++ savefig = True # and need to clear figure
++ continue
++
++ # handle comments
++ if line_stripped.startswith('#'):
++ output.extend([line])
++ continue
++
++ # deal with multilines
++ if not multiline: # not currently on a multiline
++
++ if line_stripped.endswith('\\'): # now we are
++ multiline = True
++ cont_len = len(str(lineno)) + 2
++ line_to_process = line.strip('\\')
++ output.extend([u"%s %s" % (fmtin%lineno,line)])
++ continue
++ else: # no we're still not
++ line_to_process = line.strip('\\')
++ else: # we are currently on a multiline
++ line_to_process += line.strip('\\')
++ if line_stripped.endswith('\\'): # and we still are
++ continuation = '.' * cont_len
++ output.extend([(u' %s: '+line_stripped) % continuation])
++ continue
++ # else go ahead and run this multiline then carry on
++
++ # get output of line
++ self.process_input_line(unicode(line_to_process.strip()),
++ store_history=False)
++ out_line = self.cout.getvalue()
++ self.clear_cout()
++
++ # clear current figure if plotted
++ if savefig:
++ self.ensure_pyplot()
++ self.process_input_line('plt.clf()', store_history=False)
++ self.clear_cout()
++ savefig = False
++
++ # line numbers don't actually matter, they're replaced later
++ if not multiline:
++ in_line = u"%s %s" % (fmtin%lineno,line)
+
+-def ipython_directive(name, arguments, options, content, lineno,
+- content_offset, block_text, state, state_machine,
+- ):
+-
+- debug = ipython_directive.DEBUG
+- shell.is_suppress = options.has_key('suppress')
+- shell.is_doctest = options.has_key('doctest')
+- shell.is_verbatim = options.has_key('verbatim')
+-
+- #print 'ipy', shell.is_suppress, options
+- parts = '\n'.join(content).split('\n\n')
+- lines = ['.. sourcecode:: ipython', '']
+-
+- figures = []
+- for part in parts:
+- block = block_parser(part)
+-
+- if len(block):
+- rows, figure = shell.process_block(block)
+- for row in rows:
+- lines.extend([' %s'%line for line in row.split('\n')])
+-
+- if figure is not None:
+- figures.append(figure)
+-
+- for figure in figures:
+- lines.append('')
+- lines.extend(figure.split('\n'))
+- lines.append('')
+-
+- #print lines
+- if len(lines)>2:
+- if debug:
+- print '\n'.join(lines)
+- else:
+- #print 'INSERTING %d lines'%len(lines)
+- state_machine.insert_input(
+- lines, state_machine.input_lines.source(0))
++ output.extend([in_line])
++ else:
++ output.extend([(u' %s: '+line_stripped) % continuation])
++ multiline = False
++ if len(out_line):
++ output.extend([out_line])
++ output.extend([u''])
++
++ return output
++
++class IpythonDirective(Directive):
++
++ has_content = True
++ required_arguments = 0
++ optional_arguments = 4 # python, suppress, verbatim, doctest
++ final_argumuent_whitespace = True
++ option_spec = { 'python': directives.unchanged,
++ 'suppress' : directives.flag,
++ 'verbatim' : directives.flag,
++ 'doctest' : directives.flag,
++ }
++
++ shell = EmbeddedSphinxShell()
++
++ def get_config_options(self):
++ # contains sphinx configuration variables
++ config = self.state.document.settings.env.config
++
++ # get config variables to set figure output directory
++ confdir = self.state.document.settings.env.app.confdir
++ savefig_dir = config.ipython_savefig_dir
++ source_dir = os.path.dirname(self.state.document.current_source)
++ if savefig_dir is None:
++ savefig_dir = config.html_static_path
++ if isinstance(savefig_dir, list):
++ savefig_dir = savefig_dir[0] # safe to assume only one path?
++ savefig_dir = os.path.join(confdir, savefig_dir)
++
++ # get regex and prompt stuff
++ rgxin = config.ipython_rgxin
++ rgxout = config.ipython_rgxout
++ promptin = config.ipython_promptin
++ promptout = config.ipython_promptout
++
++ return savefig_dir, source_dir, rgxin, rgxout, promptin, promptout
++
++ def setup(self):
++ # get config values
++ (savefig_dir, source_dir, rgxin,
++ rgxout, promptin, promptout) = self.get_config_options()
++
++ # and attach to shell so we don't have to pass them around
++ self.shell.rgxin = rgxin
++ self.shell.rgxout = rgxout
++ self.shell.promptin = promptin
++ self.shell.promptout = promptout
++ self.shell.savefig_dir = savefig_dir
++ self.shell.source_dir = source_dir
++
++ # setup bookmark for saving figures directory
++
++ self.shell.process_input_line('bookmark ipy_savedir %s'%savefig_dir,
++ store_history=False)
++ self.shell.clear_cout()
++
++ return rgxin, rgxout, promptin, promptout
++
++
++ def teardown(self):
++ # delete last bookmark
++ self.shell.process_input_line('bookmark -d ipy_savedir',
++ store_history=False)
++ self.shell.clear_cout()
++
++ def run(self):
++ debug = False
++
++ #TODO, any reason block_parser can't be a method of embeddable shell
++ # then we wouldn't have to carry these around
++ rgxin, rgxout, promptin, promptout = self.setup()
++
++ options = self.options
++ self.shell.is_suppress = 'suppress' in options
++ self.shell.is_doctest = 'doctest' in options
++ self.shell.is_verbatim = 'verbatim' in options
++
++
++ # handle pure python code
++ if 'python' in self.arguments:
++ content = self.content
++ self.content = self.shell.process_pure_python(content)
++
++ parts = '\n'.join(self.content).split('\n\n')
++
++ lines = ['.. code-block:: ipython','']
++ figures = []
++
++ for part in parts:
++
++ block = block_parser(part, rgxin, rgxout, promptin, promptout)
++
++ if len(block):
++ rows, figure = self.shell.process_block(block)
++ for row in rows:
++ lines.extend([' %s'%line for line in row.split('\n')])
++
++ if figure is not None:
++ figures.append(figure)
++
++ #text = '\n'.join(lines)
++ #figs = '\n'.join(figures)
++
++ for figure in figures:
++ lines.append('')
++ lines.extend(figure.split('\n'))
++ lines.append('')
++
++ #print lines
++ if len(lines)>2:
++ if debug:
++ print '\n'.join(lines)
++ else: #NOTE: this raises some errors, what's it for?
++ #print 'INSERTING %d lines'%len(lines)
++ self.state_machine.insert_input(
++ lines, self.state_machine.input_lines.source(0))
++
++ text = '\n'.join(lines)
++ txtnode = nodes.literal_block(text, text)
++ txtnode['language'] = 'ipython'
++ #imgnode = nodes.image(figs)
+
+- return []
++ # cleanup
++ self.teardown()
+
+-ipython_directive.DEBUG = False
++ return []#, imgnode]
+
+ # Enable as a proper Sphinx directive
+ def setup(app):
+ setup.app = app
+- options = {'suppress': directives.flag,
+- 'doctest': directives.flag,
+- 'verbatim': directives.flag,
+- }
+
+- app.add_directive('ipython', ipython_directive, True, (0, 2, 0), **options)
++ app.add_directive('ipython', IpythonDirective)
++ app.add_config_value('ipython_savefig_dir', None, True)
++ app.add_config_value('ipython_rgxin',
++ re.compile('In \[(\d+)\]:\s?(.*)\s*'), True)
++ app.add_config_value('ipython_rgxout',
++ re.compile('Out\[(\d+)\]:\s?(.*)\s*'), True)
++ app.add_config_value('ipython_promptin', 'In [%d]:', True)
++ app.add_config_value('ipython_promptout', 'Out[%d]:', True)
+
+
+ # Simple smoke test, needs to be converted to a proper automatic test.
+@@ -488,7 +683,7 @@
+ @savefig mystinkbug.png width=4in
+ In [4]: imshow(im)
+ Out[4]: <matplotlib.image.AxesImage object at 0x39ea850>
+-
++
+ """,
+ r"""
+
+@@ -523,7 +718,7 @@
+ In [134]: numpy.random.seed(2358)
+
+ @doctest
+-In [135]: np.random.rand(10,2)
++In [135]: numpy.random.rand(10,2)
+ Out[135]:
+ array([[ 0.64524308, 0.59943846],
+ [ 0.47102322, 0.8715456 ],
+@@ -556,8 +751,6 @@
+ 7
+ 8
+ 9
+-
+-
+ """,
+
+ r"""
+@@ -597,11 +790,12 @@
+ In [153]: grid(True)
+
+ """,
+- ]
+-
++ ]
++ # skip local-file depending first example:
++ examples = examples[1:]
+
+- ipython_directive.DEBUG = True
+- #options = dict(suppress=True)
++ #ipython_directive.DEBUG = True # dbg
++ #options = dict(suppress=True) # dbg
+ options = dict()
+ for example in examples:
+ content = example.split('\n')
+@@ -613,4 +807,7 @@
+
+ # Run test suite as a script
+ if __name__=='__main__':
++ if not os.path.isdir('_static'):
++ os.mkdir('_static')
+ test()
++ print 'All OK? Check figures in _static/'
diff --git a/debian/patches/series b/debian/patches/series
index 056b3b0..f2ef593 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,4 @@
fix_FTBFS_on_KFreeBSD.patch
get_rid_off_suffix.patch
fix_vtk-5.8_compilation.patch
+ipython-0.11-migration.patch
--
Yet Another Dynamic Engine. Platform for discrete element modeling.