Ticket #7482: sagenb_7482.3.patch

File sagenb_7482.3.patch, 7.4 KB (added by mpatel, 11 years ago)

Suppress a doctest (cf. #7650). Replaces sagenb patch.

  • sagenb/misc/support.py

    # HG changeset patch
    # User William Stein <wstein@gmail.com>
    # Date 1258514927 28800
    # Node ID 6fffd917622492c637e30ddb44fb2e010631521f
    # Parent  786e754b737da451517bca86ef682580a5d4a0ce
    trac 7482 -- provide a mode so that undeclared variables magically spring into existence and object oriented notation is not necessary
    
    diff --git a/sagenb/misc/support.py b/sagenb/misc/support.py
    a b AUTHORS: 
    1010
    1111import inspect
    1212import os
     13import base64
    1314import string
    1415import sys
    1516import __builtin__
    except ImportError: 
    538539        """
    539540        return False
    540541
     542
     543########################################################################
     544#
     545# Automatic Creation of Variable Names
     546#
     547# See the docstring for automatic_names below for an explanation of how
     548# this works.
     549#
     550########################################################################
     551
     552_automatic_names = False
     553# We wrap everything in a try/catch, in case this is being imported
     554# without the sage library present, e.g., in FEMhub.
     555try:
     556    from sage.symbolic.all import Expression, SR
     557    class AutomaticVariable(Expression):
     558        """
     559        An automatically created symbolic variable with an additional
     560        __call__ method designed so that doing self(foo,...) results
     561        in foo.self(...).
     562        """
     563        def __call__(self, *args, **kwds):
     564            """
     565            Call method such that self(foo, ...) is transformed into
     566            foo.self(...).  Note that self(foo=...,...) is not
     567            transformed, it is treated as a normal symbolic
     568            substitution.
     569            """
     570            if len(args) == 0:
     571                return Expression.__call__(self, **kwds)
     572            return args[0].__getattribute__(str(self))(*args[1:], **kwds)
     573
     574    def automatic_name_eval(s, globals, max_names=10000):
     575        """
     576        Exec the string s in the scope of the globals dictionary, and
     577        if any NameError's are raised, try to fix them by defining the
     578        variable that caused the error to be raised, then eval again.
     579        Try up to max_names times.
     580       
     581        INPUT:
     582
     583           - `s` -- string
     584           - ``globals`` -- a dictionary
     585           - ``max_names`` -- a positive integer (default: 10000)
     586        """
     587        # This entire automatic naming system really boils down to
     588        # this bit of code below.  We simply try to exec the string s
     589        # in the globals namespace, defining undefined variables and
     590        # functions until everything is defined.
     591        for _ in range(max_names):
     592            try:
     593                exec s in globals
     594                return
     595            except NameError, msg:
     596                # Determine if we hit a NameError that is probably
     597                # caused by a variable or function not being defined:
     598                if len(msg.args) == 0: raise  # not NameError with specific variable name
     599                v = msg.args[0].split("'")
     600                if len(v) < 2: raise  # also not NameError with specific variable name
     601                # We did find an undefined variable: we simply define it and try again.
     602                nm = v[1]
     603                globals[nm] = AutomaticVariable(SR, SR.var(nm))
     604        raise NameError, "Too many automatic variable names and functions created (limit=%s)"%max_names
     605
     606    def automatic_name_filter(s):
     607        """
     608        Wrap the string `s` in a call that will cause evaluation of
     609        `s` to automatically create undefined variable names.
     610
     611        INPUT:
     612
     613           - `s` -- a string
     614
     615        OUTPUT:
     616
     617           - a string
     618        """
     619        return '_support_.automatic_name_eval(_support_.base64.b64decode("%s"),globals())'%base64.b64encode(s)
     620
     621    def automatic_names(state=None):
     622        """
     623        Turn automatic creation of variables and functional calling of
     624        methods on or off.  Returns the current state if no argument is
     625        given.
     626
     627        This ONLY works in the Sage notebook.  It is not supported on the
     628        command line.
     629
     630        INPUT:
     631
     632            - ``state`` -- None or bool
     633
     634        EXAMPLES::
     635
     636            sage: automatic_names(True)      # not tested
     637            sage: x + y + z                  # not tested
     638            x + y + z
     639
     640        Here, trig_expand, y, and theta are all automatically
     641        created::
     642       
     643            sage: trig_expand((2*x + 4*y + sin(2*theta))^2)   # not tested
     644            4*(sin(theta)*cos(theta) + x + 2*y)^2
     645           
     646        IMPLEMENTATION: Here's how this works, internally.  We define
     647        an AutomaticVariable class derived from Expression.  An
     648        instance of AutomaticVariable is a specific symbolic variable,
     649        but with a special call method.  We overload the call method
     650        so that ``foo(bar, ...)`` gets transformed to ``bar.foo(...)``.  At
     651        the same time, we still want expressions like `f^2 - b` to
     652        work, i.e., we don't want to have to figure out whether a name
     653        appearing in a NameError is meant to be a symbolic variable or
     654        a function name. Instead, we just make an object that is both!
     655
     656        This entire approach is very simple---we do absolutely no
     657        parsing of the actual input.  The actual real work amounts to
     658        only a few lines of code.  The primary catch to this approach
     659        is that if you evaluate a big block of code in the notebook,
     660        and the first few lines take a long time, and the next few
     661        lines define 10 new variables, the slow first few lines will
     662        be evaluated 10 times.  Of course, the advantage of this
     663        approach is that even very subtle code that might inject
     664        surprisingly named variables into the namespace will just work
     665        correctly, which would be impossible to guarantee with static
     666        parsing, no matter how sophisticated it is.  Finally, given
     667        the target audience: people wanting to simplify use of Sage
     668        for Calculus for undergrads, I think this is an acceptable
     669        tradeoff, especially given that this implementation is so
     670        simple.
     671        """
     672        global _automatic_names
     673        if state is None:
     674            return _automatic_names
     675        _automatic_names = bool(state)
     676       
     677except ImportError:
     678   
     679    pass
     680
    541681from sagenb.interfaces.format import displayhook_hack
     682
    542683def preparse_worksheet_cell(s):
    543684    """
    544685    Preparse the contents of a worksheet cell in the notebook,
    def preparse_worksheet_cell(s): 
    557698    """
    558699    if do_preparse():
    559700        s = preparse_file(s, magic=True, do_time=True, ignore_prompts=False, reload_attached=True)
    560     return displayhook_hack(s)
     701    s = displayhook_hack(s)
     702    if _automatic_names:
     703        s = automatic_name_filter(s)
     704    return s
     705
  • sagenb/notebook/worksheet.py

    diff --git a/sagenb/notebook/worksheet.py b/sagenb/notebook/worksheet.py
    a b from sagenb.notebook.all import * 
    36243624
    36253625    def preparse(self, s):
    36263626        return 'exec _support_.preparse_worksheet_cell(base64.b64decode("%s"))'%base64.b64encode(s)
    3627     #return 'exec _support_.displayhook_hack(_support_.preparse_file(base64.b64decode("%s"),magic=True,do_time=True,ignore_prompts=False,reload_attached=True))'%base64.b64encode(s)
    3628 
     3627   
     3628   
    36293629    ##########################################################
    36303630    # Loading and attaching files
    36313631    ##########################################################