hi,

On Wednesday 10 June 2009 18:02:56 Robert Bradshaw wrote:
> > hum... maybe I am not tackling this from the correct angle (perhaps
> > that a
> > simple buffer of strings filled while the last entry is not
> > the_empty_string
> > would do as I quick hack...)
>
> The way ipython does it is to require a new empty line to "leave" an
> indentation block--maybe you could do the same. (Or maybe you could
> even hook this in with ipython).

attached is my hack. feel free to steal it...
there are probably many improvements to be performed.

cheers,
sebastien.
-- 
#########################################
# Dr. Sebastien Binet
# Laboratoire de l'Accelerateur Lineaire
# Universite Paris-Sud XI
# Batiment 200
# 91898 Orsay
#########################################

#!/usr/bin/env python
# @file icython.py: a dead simple cython interpreter
# @author Sebastien Binet <[email protected]>
# @date June 2009

__version__ = "$Revision$"
__doc__ = """A dead simple cython interpreter to try out cython statements"""
__author__= "Sebastien Binet <[email protected]>"

### stdlib imports ------------------------------------------------------------
from code import InteractiveConsole

### classes -------------------------------------------------------------------
class CythonInteractiveConsole(InteractiveConsole):
    """A dead simple Cython interpreter
    """

    def __init__(self, *args, **kwds):
        # interactive console is an old-style class
        InteractiveConsole.__init__(self, *args, **kwds)
        import sys
        sys.ps1 = 'cython> '
        sys.ps2 = '.   ... '
        self._pyxbuild_dir = kwds.get('pyxbuild_dir', None)
        self.py_compile = self.compile
        
    def runcode(self, code):
        """%s""" % InteractiveConsole.runcode.__doc__
        # we need to fix-up that method as we are given a C-ext module
        # in case of cython (instead of a code-object)
        import types
        if isinstance(code, types.ModuleType):
            # slam the content of the module into our local namespace
            for k,v in code.__dict__.iteritems():
                if not k.startswith('__'):
                    self.locals[k] = v
        else:
            return InteractiveConsole.runcode(self, code)

    def runsource(self, source, filename="<input>", symbol="single"):
        kwds = dict(source=source, filename=filename, symbol=symbol)
        try:
            code = self.cython_compile(source, filename, symbol)
        except (OverflowError, SyntaxError, ValueError):
            # Case 1
            self.showsyntaxerror(filename)
            return False

        if code is None:
            # Case 2
            return True

        # Case 3
        self.runcode(code)
        return False

    def cython_compile(self, source, filename, symbol):
        try:
            # first try normal python...
            return self.compile(source, filename, symbol)
        except SyntaxError, py_err:
            # maybe a cython-construct...
            try:
                fname = _maybe_cython_compile(ctx=self, source=source)
                if fname is None:
                    # more input needed...
                    return
                from pyximport import load_module as cy_load_module
                mod = cy_load_module("_cython_gen_%s" % id(source), fname)
                import os
                os.remove(fname)
                return mod
            except Exception, cython_err:
                raise SyntaxError(cython_err)
    pass # class CythonInteractiveConsole

### utils ---------------------------------------------------------------------
def code_to_file(source):
    import tempfile
    fd, fname = tempfile.mkstemp(prefix="cython_source_",
                                 suffix='.pyx')
    import os
    if os.path.exists(fname):
        os.remove(fname)
    f = open(fname, 'w')
    f.write(source)
    f.flush()
    f.close()
    return fname

def _maybe_cython_compile(ctx, source):
    # Check for source consisting of only blank lines and comments
    for line in source.split("\n"):
        line = line.strip()
        if line and line[0] != '#':
            break               # Leave it alone
    else:
        if symbol != "eval":
            source = "pass"     # Replace it with a 'pass' statement

    err = err1 = err2 = None
    code = code1 = code2 = None

    lines = source.split("\n")
    if lines[-1].strip() != "":
        return #
    
    from pyximport import pyxbuild
    #pyxbuild.DEBUG = 1
    pyx_to_dll = pyxbuild.pyx_to_dll

    # the following is modeled after python:codeop._maybe_compile
    try:
        fname = code_to_file(source+"\n ")
        code = pyx_to_dll(filename=fname,
                          force_rebuild=1,
                          pyxbuild_dir=ctx._pyxbuild_dir)
    except (pyxbuild.DistutilsError, pyxbuild.CCompilerError), err:
        pass

    try:
        open(fname, "a").write('\n')
        code1 = pyx_to_dll(filename=fname,
                           force_rebuild=1,
                           pyxbuild_dir=ctx._pyxbuild_dir)
    except (pyxbuild.DistutilsError, pyxbuild.CCompilerError), err1:
        pass

    try:
        open(fname, "a").write('\n')
        code2 = pyx_to_dll(filename=fname,
                           force_rebuild=1,
                           pyxbuild_dir=ctx._pyxbuild_dir)
    except (pyxbuild.DistutilsError, pyxbuild.CCompilerError), err2:
        pass

    if code and fname:
        return fname
    if not code1 and repr(err1) == repr(err2):
        raise SyntaxError, err1

### ---------------------------------------------------------------------------
if __name__ == "__main__":
    import user # allow user to inject its own python customizations...
    banner = """
###################################
# Welcome to ICython,             
#  an interactive Cython console  
#  (version=%s)                   
###################################
""" % __version__
    import sys
    cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
    banner += "\nPython %s on %s\n%s\n(%s)\n" % (
        sys.version, sys.platform, cprt,
        CythonInteractiveConsole.__name__)
    ns = dict(locals())
    for k in ('_maybe_cython_compile',
              'code_to_file', 'cprt', 'banner', 'InteractiveConsole',
              'CythonInteractiveConsole'
              ):
        del ns[k]
    icython = CythonInteractiveConsole(locals=ns)
    icython.interact(banner=banner)
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to