From 360eddd3a343ad5fdc310fb0cbf66e9d6aae31a7 Mon Sep 17 00:00:00 2001 From: Timo Kaufmann Date: Sun, 23 Dec 2018 10:08:34 +0100 Subject: [PATCH] sage: remove outdated patch files --- .../sage/patches/no-invalid-gap-test.patch | 19 - .../science/math/sage/patches/r-rpy.patch | 763 ------------------ 2 files changed, 782 deletions(-) delete mode 100644 pkgs/applications/science/math/sage/patches/no-invalid-gap-test.patch delete mode 100644 pkgs/applications/science/math/sage/patches/r-rpy.patch diff --git a/pkgs/applications/science/math/sage/patches/no-invalid-gap-test.patch b/pkgs/applications/science/math/sage/patches/no-invalid-gap-test.patch deleted file mode 100644 index 546a7876489..00000000000 --- a/pkgs/applications/science/math/sage/patches/no-invalid-gap-test.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/src/sage/libs/gap/util.pyx b/src/sage/libs/gap/util.pyx -index bdde6aa60f..50459534f8 100644 ---- a/src/sage/libs/gap/util.pyx -+++ b/src/sage/libs/gap/util.pyx -@@ -165,14 +165,6 @@ def gap_root(): - sage: from sage.libs.gap.util import gap_root - sage: gap_root() # random output - '/home/vbraun/opt/sage-5.3.rc0/local/gap/latest' -- -- If GAP_ROOT_DIR is undefined or pointing to the wrong location, -- fall back code should be used to determine gapdir:: -- -- sage: import os -- sage: os.system("GAP_ROOT_DIR=/not_a_path sage -c \"sage.libs.gap.util.gap_root()\"") -- The gap-4.5.5.spkg (or later) seems to be not installed! -- ... - """ - import os.path - if os.path.exists(GAP_ROOT_DIR): diff --git a/pkgs/applications/science/math/sage/patches/r-rpy.patch b/pkgs/applications/science/math/sage/patches/r-rpy.patch deleted file mode 100644 index ab407c8fd74..00000000000 --- a/pkgs/applications/science/math/sage/patches/r-rpy.patch +++ /dev/null @@ -1,763 +0,0 @@ -diff --git a/src/sage/doctest/test.py b/src/sage/doctest/test.py -index 2f4f74cfc2..c6c1bf9194 100644 ---- a/src/sage/doctest/test.py -+++ b/src/sage/doctest/test.py -@@ -500,12 +500,13 @@ Test ``atexit`` support in the doctesting framework:: - ....: pass - - Test the ``--memlimit`` option and ``# optional - memlimit`` --(but only on Linux):: -+(but only on Linux). If this test fails, the memory needed to -+run it may have increased. Try increasing the limit. :: - - sage: from platform import system - sage: ok = True - sage: if system() == "Linux": -- ....: P = subprocess.Popen(["sage", "-t", "--warn-long", "0", "--memlimit=2000", "memlimit.rst"], stdout=subprocess.PIPE, **kwds) -+ ....: P = subprocess.Popen(["sage", "-t", "--warn-long", "0", "--memlimit=2100", "memlimit.rst"], stdout=subprocess.PIPE, **kwds) - ....: out, err = P.communicate() - ....: ok = ("MemoryError: failed to allocate" in out) - sage: ok or out -diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py -index 51a37496c2..ba982f25f7 100644 ---- a/src/sage/interfaces/expect.py -+++ b/src/sage/interfaces/expect.py -@@ -1122,10 +1122,15 @@ If this all works, you can then make calls like: - - EXAMPLES: - -- We test all of this using the R interface. First we put -+ We test all of this using the Singular interface. First we put - 10 + 15 in the input stream:: - -- sage: r._sendstr('abc <- 10 +15;\n') -+ sage: singular._sendstr('def abc = 10 + 15;\n') -+ -+ Then we tell singular to print 10, which is an arbitrary number -+ different from the expected result 35. -+ -+ sage: singular._sendstr('10;\n') - - Here an exception is raised because 25 hasn't appeared yet in the - output stream. The key thing is that this doesn't lock, but instead -@@ -1135,7 +1140,7 @@ If this all works, you can then make calls like: - - sage: t = walltime() - sage: try: -- ....: r._expect_expr('25', timeout=0.5) -+ ....: singular._expect_expr('25', timeout=0.5) - ....: except Exception: - ....: print('Did not get expression') - Did not get expression -@@ -1145,24 +1150,24 @@ If this all works, you can then make calls like: - sage: w = walltime(t); w > 0.4 and w < 10 - True - -- We tell R to print abc, which equals 25. -+ We tell Singular to print abc, which equals 25. - - :: - -- sage: r._sendstr('abc;\n') -+ sage: singular._sendstr('abc;\n') - - Now 25 is in the output stream, so we can wait for it. - - :: - -- sage: r._expect_expr('25') -+ sage: singular._expect_expr('25') - -- This gives us everything before the 25. -+ This gives us everything before the 25, including the 10 we printed earlier. - - :: - -- sage: r._expect.before.decode('ascii') -- u'...abc;\r\n[1] ' -+ sage: singular._expect.before.decode('ascii') -+ u'...10\r\n> ' - - We test interrupting ``_expect_expr`` using the GP interface, - see :trac:`6661`. Unfortunately, this test doesn't work reliably using -@@ -1203,14 +1208,7 @@ If this all works, you can then make calls like: - - - ``string`` -- a string - -- EXAMPLES: We illustrate this function using the R interface:: -- -- sage: r._synchronize() -- sage: r._sendstr('a <- 10;\n') -- sage: r.eval('a') -- '[1] 10' -- -- We illustrate using the singular interface:: -+ EXAMPLES: We illustrate this function using the Singular interface:: - - sage: singular._synchronize() - sage: singular._sendstr('int i = 5;') -@@ -1260,7 +1258,7 @@ If this all works, you can then make calls like: - - EXAMPLES: We observe nothing, just as it should be:: - -- sage: r._synchronize() -+ sage: singular._synchronize() - - TESTS: - -diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py -index 86f401571a..f3c6120ddc 100644 ---- a/src/sage/interfaces/gp.py -+++ b/src/sage/interfaces/gp.py -@@ -254,6 +254,7 @@ class Gp(ExtraTabCompletion, Expect): - self._eval_line('default(help, "gphelp -detex");') - # logfile disabled since Expect already logs - self._eval_line('default(log,0);') -+ self._eval_line("default(nbthreads,1);") - # set random seed - self.set_seed(self._seed) - -diff --git a/src/sage/interfaces/r.py b/src/sage/interfaces/r.py -index 5c75459903..06974a2324 100644 ---- a/src/sage/interfaces/r.py -+++ b/src/sage/interfaces/r.py -@@ -268,17 +268,17 @@ from __future__ import print_function, absolute_import - from six.moves import range - import six - --from .expect import Expect, ExpectElement, ExpectFunction, FunctionElement -+from .interface import Interface, InterfaceElement, InterfaceFunction, InterfaceFunctionElement - from sage.env import DOT_SAGE - import re --import sage.rings.integer - from sage.structure.element import parent - from sage.interfaces.tab_completion import ExtraTabCompletion - from sage.docs.instancedoc import instancedoc -+from rpy2 import robjects -+from rpy2.robjects import packages -+from rpy2.robjects.conversion import localconverter - - COMMANDS_CACHE = '%s/r_commandlist.sobj'%DOT_SAGE --PROMPT = '__SAGE__R__PROMPT__> ' --prompt_re = re.compile("^>", re.M) - - #there is a mirror network, but lets take #1 for now - RRepositoryURL = "http://cran.r-project.org/" -@@ -288,12 +288,156 @@ RFilteredPackages = ['.GlobalEnv'] - # but package:base should cover this. i think. - RBaseCommands = ['c', "NULL", "NA", "True", "False", "Inf", "NaN"] - --class R(ExtraTabCompletion, Expect): -+def _setup_r_to_sage_converter(): -+ """ -+ Set up a the converter used to convert from rpy2's -+ representation of R objects to the one sage expects. -+ -+ EXAMPLES:: -+ -+ Test -+ -+ Simple numeric values are represented as vectors in R. So `1` would actually -+ be an array of length 1. We convert all vectors of length 1 to simple values, -+ whether or not they "originally" were simple values or not: -+ -+ sage: r([42]).sage() -+ 42 -+ -+ sage: r(42).sage() -+ 42 -+ -+ sage: r('c("foo")').sage() -+ 'foo' -+ -+ Arrays of length greater than one are treated normally: -+ -+ sage: r([42, 43]).sage() -+ [42, 43] -+ -+ We also convert all numeric values to integers if that is possible without -+ loss of precision: -+ -+ sage: type(r([1.0]).sage()) == int -+ True -+ -+ sage: r([1.0, 42.5]).sage() -+ [1, 42.5] -+ -+ Matrices are converted to sage matrices: -+ -+ sage: r('matrix(c(2,4,3,1,5,7), nrow=2, ncol=3)').sage() -+ [2 3 5] -+ [4 1 7] -+ -+ More complex r structures are represented by dictionaries: -+ -+ sage: r.summary(1).sage() -+ {'DATA': [1, 1, 1, 1, 1, 1], -+ '_Names': ['Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'], -+ '_r_class': ['summaryDefault', 'table']} -+ -+ sage: r.options(width="60").sage() -+ {'DATA': {'width': 60}, '_Names': 'width'} -+ -+ The conversion can handle "not a number", infintiy, imaginary values and -+ missing values: -+ -+ sage: r(-17).sqrt().sage() -+ nan -+ sage: r('-17+0i').sqrt().sage() -+ 4.123105625617661j -+ sage: r('NA').sage() -+ NA -+ sage: inf = r('Inf'); inf.sage() -+ inf -+ -+ -+ Character Vectors are represented by regular python arrays: -+ -+ sage: labs = r.paste('c("X","Y")', '1:10', sep='""'); labs.sage() -+ ['X1', 'Y2', 'X3', 'Y4', 'X5', 'Y6', 'X7', 'Y8', 'X9', 'Y10'] -+ """ -+ from rpy2.rinterface import SexpVector, ListSexpVector, FloatSexpVector -+ from rpy2.robjects.conversion import Converter -+ -+ # convert rpy2's representation of r objects to the one sage expects (as defined by the old -+ # expect interface) -+ cv = Converter('r to sage converter') -+ -+ # fallback -+ cv.ri2py.register(object, lambda obj: obj) -+ -+ def float_to_int_if_possible(f): -+ # preserve the behaviour of the old r parser, e.g. return 1 instead of 1.0 -+ return int(f) if isinstance(f, int) or f.is_integer() else round(f, 16) # TODO investigate the rounding -+ cv.ri2py.register(float, float_to_int_if_possible) -+ -+ def list_to_singleton_if_possible(l): -+ if len(l) == 1: -+ return l[0] -+ else: -+ return l -+ -+ def _vector(vec): -+ attrs = vec.list_attrs() -+ # Recursive calls have to be made explicitly -+ # https://bitbucket.org/rpy2/rpy2/issues/363/custom-converters-are-not-applied -+ data = list_to_singleton_if_possible([ cv.ri2py(val) for val in vec ]) -+ rclass = list(vec.do_slot('class')) if 'class' in attrs else vec.rclass -+ -+ if 'names' in attrs: -+ # seperate names and values, call ri2py recursively to convert elements -+ names = list_to_singleton_if_possible(list(vec.do_slot('names'))) -+ return { -+ 'DATA': data, -+ '_Names': names, -+ '_r_class': rclass, -+ } -+ else: -+ # if no names are present, convert to a normal list or a single value -+ return data -+ cv.ri2py.register(SexpVector, _vector) -+ -+ def _matrix(mat): -+ if 'dim' in mat.list_attrs(): -+ try: -+ from sage.matrix.constructor import matrix -+ dimensions = mat.do_slot("dim") -+ # TODO: higher dimensions? happens often in statistics -+ if len(dimensions) != 2: -+ raise TypeError -+ (nrow, ncol) = dimensions -+ #since R does it the other way round, we assign -+ #transposed and then transpose the matrix :) -+ m = matrix(ncol, nrow, [cv.ri2py(i) for i in mat]) -+ return m.transpose() -+ except TypeError: -+ pass -+ else: -+ return _vector(mat) -+ cv.ri2py.register(FloatSexpVector, _matrix) -+ -+ def _list_vector(vec): -+ # we have a R list (vector of arbitrary elements) -+ attrs = vec.list_attrs() -+ names = vec.do_slot('names') -+ values = [ cv.ri2py(val) for val in vec ] -+ rclass = list(vec.do_slot('class')) if 'class' in attrs else vec.rclass -+ data = zip(names, values) -+ return { -+ 'DATA': dict(data), -+ '_Names': cv.ri2py(names), -+ # '_r_class': rclass, # FIXME why not? -+ }; -+ cv.ri2py.register(ListSexpVector, _list_vector) -+ -+ return cv -+ -+class R(ExtraTabCompletion, Interface): - def __init__(self, -- maxread=None, script_subdirectory=None, -- server_tmpdir = None, -+ maxread=None, - logfile=None, -- server=None, - init_list_length=1024, - seed=None): - """ -@@ -319,46 +463,19 @@ class R(ExtraTabCompletion, Expect): - sage: r == loads(dumps(r)) - True - """ -- Expect.__init__(self, - -- # The capitalized version of this is used for printing. -- name = 'r', -+ Interface.__init__( -+ self, -+ name = 'r', # The capitalized version of this is used for printing. -+ ) - -- # This is regexp of the input prompt. If you can change -- # it to be very obfuscated that would be better. Even -- # better is to use sequence numbers. -- # options(prompt=\" \") -- prompt = '> ', #default, later comes the change -+ # It would be better to make this an attribute of `R`, but that leads to problems since -+ # we override `__getattr__`. -+ global _r_to_sage_converter -+ _r_to_sage_converter = _setup_r_to_sage_converter() - -- # This is the command that starts up your program -- # See #25806 for the --no-readline switch which fixes hangs for some -- command = "R --no-readline --vanilla --quiet", -- -- server=server, -- server_tmpdir=server_tmpdir, -- -- script_subdirectory = script_subdirectory, -- -- # If this is true, then whenever the user presses Control-C to -- # interrupt a calculation, the whole interface is restarted. -- restart_on_ctrlc = False, -- -- # If true, print out a message when starting -- # up the command when you first send a command -- # to this interface. -- verbose_start = False, -- -- logfile=logfile, -- -- # If an input is longer than this number of characters, then -- # try to switch to outputting to a file. -- eval_using_file_cutoff=1024) -- -- self.__seq = 0 -- self.__var_store_len = 0 -- self.__init_list_length = init_list_length -- self._prompt_wait = [self._prompt] - self._seed = seed -+ self._start() - - def set_seed(self, seed=None): - """ -@@ -391,14 +508,10 @@ class R(ExtraTabCompletion, Expect): - sage: r = R() - sage: r._start() - """ -- Expect._start(self) -- - # width is line width, what's a good value? maximum is 10000! - # pager needed to replace help view from less to printout - # option device= is for plotting, is set to x11, NULL would be better? -- self._change_prompt(PROMPT) -- self.eval('options(prompt=\"%s\",continue=\"%s\", width=100,pager="cat",device="png")'%(PROMPT, PROMPT)) -- self.expect().expect(PROMPT) -+ self.eval('options(width=100,pager="cat",device="png")') - self.eval('options(repos="%s")'%RRepositoryURL) - self.eval('options(CRAN="%s")'%RRepositoryURL) - -@@ -669,22 +782,17 @@ class R(ExtraTabCompletion, Expect): - ... - ImportError: ... - """ -- ret = self.eval('require("%s")' % library_name) -- if six.PY2: -- try: -- ret = ret.decode('utf-8') -- except UnicodeDecodeError: -- ret = ret.decode('latin-1') -- # try hard to parse the message string in a locale-independent way -- if ' library(' in ret: # locale-independent key-word -- raise ImportError("%s"%ret) -+ if robjects.packages.isinstalled(library_name): -+ robjects.packages.importr(library_name) - else: -- try: -- # We need to rebuild keywords! -- del self.__tab_completion -- except AttributeError: -- pass -- self._tab_completion(verbose=False, use_disk_cache=False) -+ raise ImportError("R library {} not installed".format(library_name)) -+ -+ try: -+ # We need to rebuild keywords! -+ del self.__tab_completion -+ except AttributeError: -+ pass -+ self._tab_completion(verbose=False, use_disk_cache=False) - - require = library #overwrites require - -@@ -789,17 +897,24 @@ class R(ExtraTabCompletion, Expect): - EXAMPLES:: - - sage: r.help('c') -- c package:base R Documentation -+ title -+ ----- -+ -+ Combine Values into a Vector or List -+ -+ name -+ ---- -+ -+ c - ... -- -- .. note:: -- -- This is similar to typing r.command?. - """ -- s = self.eval('help("%s")'%command).strip() # ?cmd is only an unsafe shortcut -+ s = robjects.help.pages(command)[0].to_docstring() -+ -+ # TODO what is this for? - import sage.plot.plot - if sage.plot.plot.EMBEDDED_MODE: - s = s.replace('_\x08','') -+ - return HelpExpression(s) - - def _assign_symbol(self): -@@ -914,9 +1029,19 @@ class R(ExtraTabCompletion, Expect): - '[1] 5' - """ - cmd = '%s <- %s'%(var,value) -- out = self.eval(cmd) -- if out.find("error") != -1: -- raise TypeError("Error executing code in R\nCODE:\n\t%s\nR ERROR:\n\t%s"%(cmd, out)) -+ # FIXME this is how it behaved before since the output was only compared to 'error' -+ # while the actual error message started with an upper-case 'Error'. -+ # The doctests rely on this when doing `loads(dumps(r('"abc"')))` which will load -+ # simply `"abc"` which will then again be set as `sage0 <- abc` (notice the missing -+ # quotes). The test will pass anyway because the identifier is reused for some reason. -+ # That means `sage0` will already be "abc" from the first `r('"abc"')` call. -+ from rpy2.rinterface import RRuntimeWarning, RRuntimeError -+ import warnings -+ warnings.filterwarnings("ignore", category = RRuntimeWarning) -+ try: -+ out = self.eval(cmd) -+ except RRuntimeError: -+ pass - - def get(self, var): - """ -@@ -934,9 +1059,20 @@ class R(ExtraTabCompletion, Expect): - sage: r.get('a') - '[1] 2' - """ -- s = self.eval('%s'%var) -- #return self._remove_indices_re.sub("", s).strip() -- return s -+ # FIXME again, this is how it behaved before. The doctest `L.hom(r, base_morphism=phi)` -+ # in sage/rings/function_field/function_field.py relies on this. It somehow ends up -+ # requesting a non-existant r object resulting in -+ # `RRuntimeError: Error in (function (expr, envir = parent.frame(), enclos = if (is.list(envir) || : -+ # object 'sage2' not found` -+ # I haven't figured out how or why it does that. -+ from rpy2.rinterface import RRuntimeWarning, RRuntimeError -+ import warnings -+ warnings.filterwarnings("ignore", category = RRuntimeWarning) -+ try: -+ s = self.eval('%s'%var) -+ return s -+ except RRuntimeError: -+ return '' - - def na(self): - """ -@@ -966,7 +1102,12 @@ class R(ExtraTabCompletion, Expect): - - sage: dummy = r._tab_completion(use_disk_cache=False) #clean doctest - sage: r.completions('tes') -- ['testInheritedMethods', 'testPlatformEquivalence', 'testVirtual'] -+ ['testInheritedMethods', -+ 'testInstalledBasic', -+ 'testInstalledPackage', -+ 'testInstalledPackages', -+ 'testPlatformEquivalence', -+ 'testVirtual'] - """ - return [name for name in self._tab_completion() if name[:len(s)] == s] - -@@ -986,8 +1127,7 @@ class R(ExtraTabCompletion, Expect): - """ - v = RBaseCommands - -- ll = self.eval('dput(search())') # loaded libs -- ll = self.convert_r_list(ll) -+ ll = self('search()')._sage_() # loaded libs - - for lib in ll: - if lib in RFilteredPackages: -@@ -996,9 +1136,7 @@ class R(ExtraTabCompletion, Expect): - if lib.find("package:") != 0: - continue #only packages - -- raw = self.eval('dput(objects("%s"))'%lib) -- raw = self.convert_r_list(raw) -- raw = [x.replace(".","_") for x in raw] -+ raw = self('objects("%s")'%lib)._sage_() - - #TODO are there others? many of them are shortcuts or - #should be done on another level, like selections in lists -@@ -1123,24 +1261,6 @@ class R(ExtraTabCompletion, Expect): - RFunction(self, 'plot')(*args, **kwds) - return RFunction(self, 'dev.off')() - -- def _strip_prompt(self, code): -- """ -- Remove the standard R prompt from the beginning of lines in code. -- -- INPUT: -- -- - code -- a string -- -- OUTPUT: a string -- -- EXAMPLES:: -- -- sage: s = '> a <- 2\n> b <- 3' -- sage: r._strip_prompt(s) -- ' a <- 2\n b <- 3' -- """ -- return prompt_re.sub("", code) -- - def eval(self, code, globals=None, locals=None, synchronize=True, *args, **kwds): - """ - Evaluates a command inside the R interpreter and returns the output -@@ -1151,9 +1271,8 @@ class R(ExtraTabCompletion, Expect): - sage: r.eval('1+1') - '[1] 2' - """ -- # TODO split code at ";" outside of quotes and send them as individual -- # lines without ";". -- return Expect.eval(self, code, synchronize=synchronize, *args, **kwds) -+ return str(robjects.r(code)).rstrip() -+ - - def _r_to_sage_name(self, s): - """ -@@ -1255,16 +1374,8 @@ class R(ExtraTabCompletion, Expect): - self.execute('setwd(%r)' % dir) - - --# patterns for _sage_() --rel_re_param = re.compile(r'\s([\w\.]+)\s=') --rel_re_range = re.compile(r'([\d]+):([\d]+)') --rel_re_integer = re.compile(r'([^\d])([\d]+)L') --rel_re_terms = re.compile(r'terms\s*=\s*(.*?),') --rel_re_call = re.compile(r'call\s*=\s*(.*?)\),') -- -- - @instancedoc --class RElement(ExtraTabCompletion, ExpectElement): -+class RElement(ExtraTabCompletion, InterfaceElement): - - def _tab_completion(self): - """ -@@ -1315,7 +1426,7 @@ class RElement(ExtraTabCompletion, ExpectElement): - sage: len(x) - 5 - """ -- return int(self.parent().eval('dput(length(%s))'%self.name())[:-1] ) -+ return self.parent()('length(%s)'%self.name())._sage_() - - def __getattr__(self, attrname): - """ -@@ -1777,95 +1888,9 @@ class RElement(ExtraTabCompletion, ExpectElement): - self._check_valid() - P = self.parent() - -- # This is the core of the trick: using dput -- # dput prints out the internal structure of R's data elements -- # options via .deparseOpts(control=...) -- # TODO: dput also works with a file, if things get huge! -- # [[However, using a file for output often isn't necessary -- # since pipe buffering works pretty well for output. -- # That said, benchmark this. -- William Stein]] -- exp = P.eval('dput(%s)'%self.name()) -- -- # Preprocess expression -- # example what this could be: -- # structure(list(statistic = structure(0.233549683248457, .Names = "t"), -- # parameter = structure(5.58461538461538, .Names = "df"), p.value = 0.823657802106985, -- # conf.int = structure(c(-2.41722062247400, 2.91722062247400 -- # ), conf.level = 0.95), estimate = structure(c(2.75, 2.5), .Names = c("mean of x", -- # "mean of y")), null.value = structure(0, .Names = "difference in means"), -- # alternative = "two.sided", method = "Welch Two Sample t-test", -- # data.name = "c(1, 2, 3, 5) and c(1, 2, 3, 4)"), .Names = c("statistic", -- # "parameter", "p.value", "conf.int", "estimate", "null.value", -- # "alternative", "method", "data.name"), class = "htest") -- -- # R's structure (from help): -- # structure(.Data, ...) -- # .Data: an object which will have various attributes attached to it. -- # ...: attributes, specified in 'tag=value' form, which will be -- # attached to data. -- #For historical reasons (these names are used when deparsing), -- # attributes '".Dim"', '".Dimnames"', '".Names"', '".Tsp"' and -- # '".Label"' are renamed to '"dim"', '"dimnames"', '"names"', -- # '"tsp"' and '"levels"'. -- -- -- -- # we want this in a single line -- exp.replace('\n','') -- exp = "".join(exp.split("\n")) -- -- # python compatible parameters -- exp = rel_re_param.sub(self._subs_dots, exp) -- -- # Rename class since it is a Python keyword -- exp = re.sub(' class = ', ' _r_class = ',exp) -- -- # Change 'structure' to '_r_structure' -- # TODO: check that we are outside of quotes "" -- exp = re.sub(r' structure\(', ' _r_structure(', exp) -- exp = re.sub(r'^structure\(', '_r_structure(', exp) # special case -- -- # Change 'list' to '_r_list' -- exp = re.sub(r' list\(', ' _r_list(', exp) -- exp = re.sub(r'\(list\(', '(_r_list(', exp) -- -- # Change 'a:b' to 'range(a,b+1)' -- exp = rel_re_range.sub(self._subs_range, exp) -- -- # Change 'dL' to 'Integer(d)' -- exp = rel_re_integer.sub(self._subs_integer, exp) -- -- # Wrap the right hand side of terms = ... in quotes since it -- # has a ~ in it. -- exp = rel_re_terms.sub(r'terms = "\1",', exp) -- -- -- # Change call = ..., to call = "...", -- exp = rel_re_call.sub(r'call = "\1",', exp) -- -- # seems to work for -- # rr = r.summary(r.princomp(r.matrix(r.c(1,2,3,4,3,4,1,2,2),4))) -- # rr._sage_() -- # but the call expression get's evaluated. why?!? TODO -- -- -- # translation: -- # c is an ordered list -- # list is a dictionary (where _Names give the entries names. -- # map entries in names to (value, name) in each entry? -- # structure is .. see above .. structure(DATA,**kw) -- # TODO: thinking of just replacing c( with ( to get a long tuple? -- -- -- exp = self._convert_nested_r_list(exp) -- -- # Set up the globals -- globs = {'NA':None, 'NULL':None, 'FALSE':False, 'TRUE':True, -- '_r_list':self._r_list, '_r_structure':self._r_structure, -- 'Integer':sage.rings.integer.Integer, -- 'character':str} -- -- return eval(exp, globs, globs) -+ with localconverter(_r_to_sage_converter) as cv: -+ parsed = robjects.r(self.name()) -+ return parsed - - - def _latex_(self): -@@ -1893,7 +1918,7 @@ class RElement(ExtraTabCompletion, ExpectElement): - - - @instancedoc --class RFunctionElement(FunctionElement): -+class RFunctionElement(InterfaceFunctionElement): - def __reduce__(self): - """ - EXAMPLES:: -@@ -1917,9 +1942,16 @@ class RFunctionElement(FunctionElement): - sage: a = r([1,2,3]) - sage: length = a.length - sage: print(length.__doc__) -- length package:base R Documentation -- ... -+ title -+ ----- -+ -+ Length of an Object -+ -+ name -+ ---- - -+ length -+ ... - """ - M = self._obj.parent() - return M.help(self._name) -@@ -1951,7 +1983,7 @@ class RFunctionElement(FunctionElement): - - - @instancedoc --class RFunction(ExpectFunction): -+class RFunction(InterfaceFunction): - def __init__(self, parent, name, r_name=None): - """ - A Function in the R interface. -@@ -2007,9 +2039,16 @@ class RFunction(ExpectFunction): - - sage: length = r.length - sage: print(length.__doc__) -- length package:base R Documentation -- ... -+ title -+ ----- -+ -+ Length of an Object - -+ name -+ ---- -+ -+ length -+ ... - """ - M = self._parent - return M.help(self._name) -diff --git a/src/sage/stats/r.py b/src/sage/stats/r.py -index cd2002559b..8a2f243901 100644 ---- a/src/sage/stats/r.py -+++ b/src/sage/stats/r.py -@@ -39,12 +39,12 @@ def ttest(x,y,conf_level = 0.95, **kw): - - Example:: - -- sage: a, b = ttest([1,2,3,4,5],[1,2,3,3.5,5.121]); a -- 0.941026372027427 -+ sage: a, b = ttest([1,2,3,4,5],[1,2,3,3.5,5.121]); a # abs tol 1e-12 -+ 0.9410263720274274 - """ - if len(x) != len(y): - raise AttributeError("vectors x and y must be of same length") - - test = myR.t_test(x,y,conf_level = conf_level, **kw)._sage_() -- t = test.get('DATA').get('p_value') -+ t = test.get('DATA').get('p.value') - return t, test