[SCM] Yet Another Dynamic Engine. Platform for discrete element modeling. branch, master, updated. upstream/0.70.0-109-g22291a8

Anton Gladky gladky.anton at gmail.com
Fri Nov 25 19:33:10 UTC 2011


The following commit has been merged in the master branch:
commit 6c190370c1f08ad0eb5ed3b416e4eacf909267a3
Author: Anton Gladky <gladky.anton at gmail.com>
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.



More information about the debian-science-commits mailing list