Ticket #839: 839-r-pexpect-initial.patch

File 839-r-pexpect-initial.patch, 22.7 KB (added by mhansen, 13 years ago)
  • sage/interfaces/all.py

    # HG changeset patch
    # User Mike Hansen <mhansen@gmail.com>
    # Date 1204126586 28800
    # Node ID 57294180a9410241b945c30762ad12be46d6d1f6
    # Parent  63a87311900f9f2181d0b73f676f07841782e208
    Initial version of the R pexpect interface.
    
    diff -r 63a87311900f -r 57294180a941 sage/interfaces/all.py
    a b from ecm import ECM, ecm 
    2929from ecm import ECM, ecm
    3030from povray import povray
    3131from lie import lie, lie_console, LiE
     32from r import r, r_console, R
    3233
    3334# signal handling
    3435from get_sigs import *
  • sage/interfaces/expect.py

    diff -r 63a87311900f -r 57294180a941 sage/interfaces/expect.py
    a b If this all works, you can then make cal 
    605605    def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True):
    606606        #if line.find('\n') != -1:
    607607        #    raise ValueError, "line must not contain any newlines"
     608
     609        try:
     610            self._synchronize()
     611        except AttributeError:
     612            pass
     613           
    608614        if allow_use_file and self._eval_using_file_cutoff and len(line) > self._eval_using_file_cutoff:
    609615            return self._eval_line_using_file(line)
    610616        try:
  • new file sage/interfaces/r.py

    diff -r 63a87311900f -r 57294180a941 sage/interfaces/r.py
    - +  
     1r"""
     2R Interface
     3
     4The following examples try to follow "An Introduction to R" which can
     5be found at http://cran.r-project.org/doc/manuals/R-intro.html .
     6
     7EXAMPLES:
     8
     92 Simple manipulations; numbers and vectors
     10
     11The simplest data structure in R is the numeric vector which
     12consists of an ordered collection of numbers.  To create a
     13vector named x using the R interface in SAGE, you pass the
     14R interpreter object a list or tuple of numbers.
     15    sage: x = r([10.4,5.6,3.1,6.4,21.7]); x
     16    10.4  5.6  3.1  6.4 21.7
     17
     18You can invert elements of a vector x in R by using the
     19invert operator or by doing 1/x.
     20    sage: ~x
     21    0.09615385 0.17857143 0.32258065 0.15625000 0.04608295
     22    sage: 1/x
     23    0.09615385 0.17857143 0.32258065 0.15625000 0.04608295
     24
     25The following assignemnt creates a vector y with 11 entries which
     26consists of two copies of x with a 0 in between.
     27    sage: y = r([x,0,x]); y
     28    10.4  5.6  3.1  6.4 21.7  0.0 10.4  5.6  3.1  6.4 21.7
     29
     30=Vector Arithmetic=
     31
     32The following command generates a new vector v of length 11 constructed
     33by adding together (element by element) 2*x repeated 2.2 times, y
     34repeated just once, and 1 repeated 11 times.
     35    sage: v = 2*x+y+1; v
     36    32.2 17.8 10.3 20.2 66.1 21.8 22.6 12.8 16.9 50.8 43.5
     37
     38One can compute the sum of the elements of an R vector in the following
     39two ways:
     40    sage: sum(x)
     41    47.2
     42    sage: x.sum()
     43    47.2
     44
     45One can calculate the sample variance of a list of numbers:
     46    sage: ((x-x.mean())^2/(x.length()-1)).sum()
     47    53.853
     48    sage: x.var()
     49    53.853
     50
     51   
     52    sage: x.sort()
     53    3.1  5.6  6.4 10.4 21.7
     54    sage: x.min()
     55    3.1
     56    sage: x.max()
     57    21.7
     58    sage: x
     59    10.4  5.6  3.1  6.4 21.7
     60
     61
     62
     63    sage: r(-17).sqrt()
     64    NaN
     65    sage: r('-17+0i').sqrt()
     66    0+4.123106i
     67
     68=Generating Regular Sequences=
     69
     70    sage: r('1:10')
     71    1  2  3  4  5  6  7  8  9 10
     72    sage: list(_)
     73    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     74
     75Because 'from' is a keyword in Python, it can't be used
     76as a keyword argument.  Instead, 'from_' can be passed, and
     77R will recognize it as the correct thing. 
     78    sage: r.seq(length=10, from_=-1, by=.2)
     79    -1.0 -0.8 -0.6 -0.4 -0.2  0.0  0.2  0.4  0.6  0.8
     80
     81
     82    sage: x = r([10.4,5.6,3.1,6.4,21.7]);
     83    sage: x.rep(2)
     84    10.4  5.6  3.1  6.4 21.7 10.4  5.6  3.1  6.4 21.7
     85    sage: x.rep(times=2)
     86    10.4  5.6  3.1  6.4 21.7 10.4  5.6  3.1  6.4 21.7
     87    sage: x.rep(each=2)
     88    10.4 10.4  5.6  5.6  3.1  3.1  6.4  6.4 21.7 21.7
     89
     90
     91=Logical Vectors=
     92
     93
     94=Missing Values=
     95sage: na = r('NA')
     96sage: z = r([1,2,3,na])
     97sage: z
     98 1  2  3 NA
     99sage: ind = r.is_na(z)
     100sage: ind
     101FALSE FALSE FALSE  TRUE
     102sage: zero = r(0)
     103sage: zero / zero
     104NaN
     105sage: inf = r('Inf')
     106sage: inf-inf
     107NaN
     108sage: r.is_na(inf)
     109FALSE
     110sage: r.is_na(inf-inf)
     111TRUE
     112sage: r.is_na(zero/zero)
     113TRUE
     114sage: r.is_na(na)
     115TRUE
     116sage: r.is_nan(inf-inf)
     117TRUE
     118sage: r.is_nan(zero/zero)
     119TRUE
     120sage: r.is_nan(na)
     121FALSE
     122
     123
     124=Character Vectors=
     125
     126sage: labs = r.paste('c("X","Y")', '1:10', sep='""'); labs
     127"X1"  "Y2"  "X3"  "Y4"  "X5"  "Y6"  "X7"  "Y8"  "X9"  "Y10"
     128
     129
     130=Index vectors; selecting and modifying subsets of a data set=
     131
     132sage: na = r('NA')
     133sage: x = r([10.4,5.6,3.1,6.4,21.7,na]); x
     13410.4  5.6  3.1  6.4 21.7   NA
     135sage: x['!is.na(self)']
     13610.4  5.6  3.1  6.4 21.7
     137
     138
     139sage: x = r([10.4,5.6,3.1,6.4,21.7,na]); x
     14010.4  5.6  3.1  6.4 21.7   NA
     141sage: (x+1)['(!is.na(self)) & self>0']
     14211.4  6.6  4.1  7.4 22.7
     143sage: x = r([10.4,-2,3.1,-0.5,21.7,na]); x
     14410.4 -2.0  3.1 -0.5 21.7   NA
     145sage: (x+1)['(!is.na(self)) & self>0']
     14611.4  4.1  0.5 22.7
     147
     148
     149
     150AUTHORS:
     151    -- Mike Hansen (2007-11-01)
     152    -- William Stein
     153"""
     154
     155##########################################################################
     156#
     157#       Copyright (C) 2007 William Stein <wstein@gmail.com>
     158#                     2007 Mike Hansen   <mhansen@gmail.com>
     159#
     160#  Distributed under the terms of the GNU General Public License (GPL)
     161#
     162#                  http://www.gnu.org/licenses/
     163#
     164##########################################################################
     165
     166from keyword import iskeyword
     167from expect import Expect, ExpectElement, ExpectFunction, FunctionElement
     168from sage.misc.misc import verbose, DOT_SAGE
     169from sage.misc.sage_eval import sage_eval
     170import pexpect
     171from random import randrange
     172import re
     173
     174COMMANDS_CACHE = '%s/r_commandlist_cache.sobj'%DOT_SAGE
     175
     176class R(Expect):
     177    """
     178    [[Some basic help about your system.  This is what
     179      will be displayed when somebody write mysystem?.]]
     180    """
     181    def __init__(self, stacksize=10000000,   # 10MB
     182                 maxread=100000, script_subdirectory=None,
     183                 server_tmpdir = None,
     184                 logfile=None,
     185                 server=None,
     186                 init_list_length=1024):
     187        Expect.__init__(self,
     188
     189                        # The capitalized version of this is used for printing.
     190                        name = 'r',
     191
     192                        # This is regexp of the input prompt.  If you can change
     193                        # it to be very obfuscated that would be better.   Even
     194                        # better is to use sequence numbers.
     195                        prompt = '> ',
     196
     197                        # This is the command that starts up your program
     198                        command = "R",
     199
     200                        maxread = maxread,
     201
     202                        server=server,
     203                        server_tmpdir=server_tmpdir,
     204
     205                        script_subdirectory = script_subdirectory,
     206
     207                        # If this is true, then whenever the user presses Control-C to
     208                        # interrupt a calculation, the whole interface is restarted.
     209                        restart_on_ctrlc = False,
     210
     211                        # If true, print out a message when starting
     212                        # up the command when you first send a command
     213                        # to this interface.
     214                        verbose_start = False,
     215
     216                        logfile=logfile,
     217
     218                        # If an input is longer than this number of characters, then
     219                        # try to switch to outputing to a file.
     220                        eval_using_file_cutoff=1024)
     221       
     222        self.__seq = 0
     223        self.__var_store_len = 0
     224        self.__init_list_length = init_list_length
     225        self._prompt_wait = [self._prompt]
     226        self._remove_indices_re = re.compile(r"^\s*\[\d*\]", re.M)
     227
     228    def _repr_(self):
     229        return 'R Interpreter'
     230
     231    def __reduce__(self):
     232        return reduce_load_r, tuple([])
     233   
     234    def __getattr__(self, attrname):
     235        if attrname[:1] == "_":
     236            raise AttributeError
     237        return RFunction(self, attrname)
     238
     239    def _quit_string(self):
     240        return 'quit(save="no")'
     241   
     242    def _read_in_file_command(self, filename):
     243        raise NotImplementedError       
     244
     245    #def trait_names(self):
     246    #    ## [[implement giving a list of all functions and identifiers in the system]]
     247    #    raise NotImplementedError       
     248       
     249    def read(self, filename):
     250        # [[implement loading of the contents of filename into the system]]
     251        raise NotImplementedError       
     252
     253    def _install_hints(self):
     254        """
     255        Hints for installing R on your computer.
     256
     257        AUTHOR:
     258            -- Mike Hansen (2007-11-01)
     259        """
     260        return """"""
     261
     262
     263    def kill(self, var):
     264        # [[send code that kills the variable with given name in the system.]]
     265        return "rm %s"%var
     266       
     267    def console(self):
     268        # run the console command (defined below).
     269        return "R"
     270
     271    def version(self):
     272        # run the version command (defined below)
     273        s = self.eval('version')
     274        version_string = 'version.string '
     275        i = s.find(version_string)
     276        return s[len(version_string)+i:]
     277   
     278    def _object_class(self):
     279        return RElement
     280
     281    def _true_symbol(self):
     282        # return the string rep of truth, i.e., what the system outputs
     283        # when you type 1==1.
     284        return "TRUE"
     285
     286    def _false_symbol(self):
     287        # return the string rep of truth, i.e., what the system outputs
     288        # when you type 1==2.
     289        return "FALSE"
     290       
     291    def _equality_symbol(self):
     292        # return the symbol for checking equality, e.g., == or eq.
     293        return "=="
     294
     295    def help(self, command):
     296        # return help on a given command.
     297        raise NotImplementedError
     298
     299    def _assign_symbol(self):
     300        return " <- "
     301
     302    def _left_list_delim(self):
     303        return "c("
     304
     305    def _right_list_delim(self):
     306        return ")"
     307
     308    def console(self):
     309        r_console()
     310
     311    def function_call(self, function, args=[], kwargs={}):
     312        if function == '':
     313            raise ValueError, "function name must be nonempty"
     314        if function[:2] == "__":
     315            raise AttributeError
     316        if not isinstance(args, list):
     317            args = [args]
     318        for i in range(len(args)):
     319            if not isinstance(args[i], ExpectElement):
     320                args[i] = self.new(args[i])
     321
     322        for key in kwargs:
     323            if not isinstance(kwargs[key], RElement):
     324                kwargs[key] = self.new(kwargs[key])
     325               
     326        return self.new("%s(%s)"%(function, ",".join([s.name() for s in args] + [self._sage_to_r_name(key)+'='+kwargs[key].name() for key in kwargs ] )))
     327
     328    def call(self, function_name, *args, **kwargs):
     329        return self.function_call(function_name, args=args, kwargs=kwargs)
     330
     331    def _an_element_impl(self):
     332        return self(0)
     333   
     334    def set(self, var, value):
     335        """
     336        Set the variable var to the given value.
     337        """
     338        cmd = '%s <- %s'%(var,value)
     339        out = self.eval(cmd)
     340        if out.find("error") != -1:
     341            raise TypeError, "Error executing code in R\nCODE:\n\t%s\nR ERROR:\n\t%s"%(cmd, out)
     342
     343    def get(self, var):
     344        """
     345        Get the value of the variable var.
     346        """
     347        s = self.eval('%s'%var)
     348        return self._remove_indices_re.sub("", s).strip()
     349
     350
     351    def na(self):
     352        """
     353        Returns the NA in R.
     354
     355        EXAMPLES:
     356            sage: r.na()
     357            NA
     358        """
     359        return self('NA')
     360   
     361    def completions(self, s):
     362        """
     363        Return all commands that complete the command starting with the
     364        string s.   This is like typing s[Ctrl-T] in the R interpreter.
     365        """
     366        return []
     367
     368    def _commands(self):
     369        """
     370        Return list of all commands defined in R.
     371        """
     372        try:
     373            v = sum([self.completions(chr(65+n)) for n in range(26)], []) + \
     374                sum([self.completions(chr(97+n)) for n in range(26)], [])
     375        except RuntimeError:
     376            print "\n"*3
     377            print "*"*70
     378            print "WARNING: You do not have a working version of R installed!"
     379            print "*"*70
     380            v = []
     381        v.sort()
     382        return v
     383
     384    def trait_names(self, verbose=True, use_disk_cache=True):
     385        try:
     386            return self.__trait_names
     387        except AttributeError:
     388            import sage.misc.persist
     389            if use_disk_cache:
     390                try:
     391                    self.__trait_names = sage.misc.persist.load(COMMANDS_CACHE)
     392                    return self.__trait_names
     393                except IOError:
     394                    pass
     395            if verbose:
     396                print "\nBuilding R command completion list (this takes"
     397                print "a few seconds only the first time you do it)."
     398                print "To force rebuild later, delete %s."%COMMANDS_CACHE
     399            v = self._commands()
     400            self.__trait_names = v
     401            if len(v) > 200:
     402                # R is actually installed.
     403                sage.misc.persist.save(v, COMMANDS_CACHE)
     404            return v
     405
     406    def _sendstr(self, str):
     407        if self._expect is None:
     408            self._start()
     409        try:
     410            os.write(self._expect.child_fd, str)
     411        except OSError:
     412            self._crash_msg()
     413            self.quit()
     414            self._sendstr(str)
     415           
     416    def _synchronize(self):
     417        """
     418        Synchronize pexpect interface.
     419
     420        This put a random integer (plus one!) into the output stream,
     421        then waits for it, thus resynchronizing the stream.  If the
     422        random integer doesn't appear within 1 second, R is sent
     423        interrupt signals.
     424
     425        This way, even if you somehow left R in a busy state
     426        computing, calling _synchronize gets everything fixed.
     427        """
     428        if self._expect is None: return
     429        r = randrange(2147483647)
     430        s = str(r+1)
     431        cmd = "1+%s;\n"%r
     432        self._sendstr(cmd)
     433        try:
     434            self._expect_expr(timeout=0.5)
     435            if not s in self._expect.before:
     436                self._expect_expr(s,timeout=0.5)
     437                self._expect_expr(timeout=0.5)
     438        except pexpect.TIMEOUT, msg:
     439            self._interrupt()
     440        except pexpect.EOF:
     441            self._crash_msg()
     442            self.quit()
     443           
     444    def _expect_expr(self, expr=None, timeout=None):
     445        if expr is None:
     446            expr = self._prompt_wait
     447        if self._expect is None:
     448            self._start()
     449        try:
     450            if timeout:
     451                i = self._expect.expect(expr,timeout=timeout)
     452            else:
     453                i = self._expect.expect(expr)
     454            if i > 0:
     455                v = self._expect.before
     456                self.quit()
     457                raise ValueError, "%s\nComputation failed due to a bug in R -- NOTE: Maxima had to be restarted."%v
     458        except KeyboardInterrupt, msg:
     459            #print self._expect.before
     460            i = 0
     461            while True:
     462                try:
     463                    print "Control-C pressed.  Interrupting R. Please wait a few seconds..."
     464                    self._sendstr('quit;\n'+chr(3))
     465                    self._sendstr('quit;\n'+chr(3))
     466                    self.interrupt()
     467                    self.interrupt()
     468                except KeyboardInterrupt:
     469                    i += 1
     470                    if i > 10:
     471                        break
     472                    pass
     473                else:
     474                    break
     475            raise KeyboardInterrupt, msg
     476
     477   
     478    #####################
     479    def plot(self, *args, **kwargs):
     480        return self.function_call('plot', args=args, kwargs=kwargs)
     481
     482
     483    #####################
     484    def _r_to_sage_name(self, s):
     485        """
     486        EXAMPLES:
     487            sage: f = r._r_to_sage_name
     488            sage: f('t.test')
     489            't_test'
     490            sage: f('attr<-')
     491            'attr__'
     492            sage: f('parent.env<-')
     493            'parent_env__'
     494            sage: f('class')
     495            'class_'
     496        """
     497        s = s.replace('.', '_')
     498        s = s.replace('<-', '__')
     499        if iskeyword(s):
     500            s += '_'
     501        return s
     502
     503    def _sage_to_r_name(self, s):
     504        """
     505        EXAMPLES:
     506            sage: f = r._sage_to_r_name
     507            sage: f('t_test')
     508            't.test'
     509            sage: f('attr__')
     510            'attr<-'
     511            sage: f('parent_env__')
     512            'parent.env<-'
     513            sage: f('class_')
     514            'class'
     515        """
     516        if len(s) > 1 and s[-2:] == "__":
     517            s = s[:-2] + '<-'
     518        if len(s) > 0 and s[-1] == '_':
     519            s = s[:-1]
     520        s = s.replace('_', '.')
     521        return s
     522
     523    def __getitem__(self, s):
     524        """
     525        Returns the RFunction s.
     526
     527        EXAMPLES:
     528            sage: r['as.data.frame']
     529            as.data.frame
     530            sage: r['print']
     531            print
     532            sage: r['$']
     533            $
     534        """
     535        return RFunction(self, s, r_name=True)
     536   
     537class RElement(ExpectElement):
     538    """
     539    Describe elements of your system here.
     540    """
     541    def trait_names(self):
     542        # This is if your system doesn't really have types.  If you have types
     543        # this function should only return the relevant methods that take self
     544        # as their first argument.
     545        return self.parent().trait_names()
     546
     547    def __len__(self):
     548        """
     549        EXAMPLES:
     550            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     551            sage: len(x)
     552            5
     553        """
     554        return sage_eval(self.parent().eval('length(%s)'%self.name())[4:] )
     555   
     556    def __getattr__(self, attrname):
     557        self._check_valid()
     558        if attrname[:1] == "_":
     559            raise AttributeError
     560        return RFunctionElement(self, attrname)
     561
     562    def __getitem__(self, n):
     563        """
     564        EXAMPLES:
     565            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     566            sage: x[0]
     567            numeric(0)
     568            sage: x[1]
     569            10.4
     570            sage: x[-1]
     571            5.6  3.1  6.4 21.7
     572            sage: x[-2]
     573            10.4  3.1  6.4 21.7
     574            sage: x[-3]
     575            10.4  5.6  6.4 21.7
     576            sage: x[4]
     577            6.4
     578
     579        """
     580        P = self._check_valid()
     581        if isinstance(n, basestring):
     582            n = n.replace('self', self._name)
     583            return P.new('%s[%s]'%(self._name, n))
     584        elif not isinstance(n, tuple):
     585            return P.new('%s[%s]'%(self._name, n))
     586        else:
     587            return P.new('%s[%s]'%(self._name, str(n)[1:-1]))
     588
     589    def __nonzero__(self):
     590        """
     591        bool(self) will only return True if self == 0 contains
     592        a FALSE.
     593
     594        EXAMPLES:
     595            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     596            sage: bool(x)
     597            True
     598            sage: y = r([0,0,0,0])
     599            sage: bool(y)
     600            False
     601            sage: bool(r(0))
     602            False
     603            sage: bool(r(1))
     604            True
     605
     606        """
     607        return "FALSE" in repr(self==0)
     608   
     609    def _comparison(self, other, symbol):
     610        """
     611        TESTS:
     612            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     613            sage: x._comparison(10.4, "==")
     614            TRUE FALSE FALSE FALSE FALSE
     615
     616        """
     617        P = self.parent()
     618        other = P(other)
     619        return P('%s %s %s'%(self.name(), symbol, other.name()))
     620   
     621    def __eq__(self, other):
     622        """
     623        TESTS:
     624            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     625            sage: x == 10.4
     626            TRUE FALSE FALSE FALSE FALSE
     627        """
     628        return self._comparison(other, "==")
     629   
     630    def __lt__(self, other):
     631        """
     632        TESTS:
     633            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     634            sage: x < 7
     635            FALSE  TRUE  TRUE  TRUE FALSE
     636
     637        """
     638        return self._comparison(other, "<")
     639   
     640    def __gt__(self, other):
     641        """
     642        TESTS:
     643            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     644            sage: x > 8
     645            TRUE FALSE FALSE FALSE  TRUE
     646
     647        """
     648        return self._comparison(other, ">")
     649   
     650    def __le__(self, other):
     651        """
     652        TESTS:
     653            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     654            sage: x <= 10.4
     655            TRUE  TRUE  TRUE  TRUE FALSE
     656
     657        """
     658        return self._comparison(other, "<=")
     659   
     660    def __ge__(self, other):
     661        """
     662        TESTS:
     663            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     664            sage: x >= 10.4
     665            TRUE FALSE FALSE FALSE  TRUE
     666
     667        """
     668        return self._comparison(other, ">=")
     669   
     670    def __ne__(self, other):
     671        """
     672        TESTS:
     673            sage: x = r([10.4,5.6,3.1,6.4,21.7])
     674            sage: x != 10.4
     675            FALSE  TRUE  TRUE  TRUE  TRUE
     676
     677        """
     678        return self._comparison(other, "!=")
     679   
     680    def __cmp__(self, other):
     681        P = self.parent()
     682        if P.eval("%s %s %s"%(self.name(), P._equality_symbol(),
     683                                 other.name())) == P._true_symbol():
     684            return 0
     685        elif P.eval("%s %s %s"%(self.name(), P._lessthan_symbol(), other.name())) == P._true_symbol():
     686            return -1
     687        elif P.eval("%s %s %s"%(self.name(), P._greaterthan_symbol(), other.name())) == P._true_symbol():
     688            return 1
     689        else:
     690            return -1  # everything is supposed to be comparable in Python, so we define
     691                       # the comparison thus when no comparable in interfaced system.
     692
     693
     694class RFunctionElement(FunctionElement):
     695    def _sage_doc_(self):
     696        M = self._obj.parent()
     697        return M.help(self._name)
     698       
     699    def __call__(self, *args, **kwargs):
     700        return self._obj.parent().function_call(self._name, args=[self._obj] + list(args), kwargs=kwargs)
     701   
     702   
     703class RFunction(ExpectFunction):
     704    def __init__(self, parent, name, r_name=False):
     705        self._parent = parent
     706        if r_name:
     707            self._name = name
     708        else:
     709            self._name = parent._sage_to_r_name(name)
     710       
     711    def _sage_doc_(self):
     712        M = self._parent
     713        return M.help(self._name)
     714
     715   
     716    def __call__(self, *args, **kwargs):
     717        return self._parent.function_call(self._name, args=list(args), kwargs=kwargs)
     718   
     719def is_RElement(x):
     720    return isinstance(x, RElement)
     721
     722# An instance
     723r = R()
     724
     725def reduce_load_R():
     726    return r
     727
     728import os
     729def r_console():
     730    # This will only spawn local processes
     731    os.system('R')
     732
     733
     734## def r_version():
     735##     """
     736##     EXAMPLES:
     737##         sage: r.version()
     738##         ???
     739##     """
     740##     raise NotImplementedError