Revision: 641
http://rpy.svn.sourceforge.net/rpy/?rev=641&view=rev
Author: lgautier
Date: 2008-08-25 07:08:15 +0000 (Mon, 25 Aug 2008)
Log Message:
-----------
rinterface:
- fixed signature for Sexp_get getter
- added emptyEnv
- new method Sexp_do_slot_assign
rlike:
- added paramater 'cmp' to order()
robjects:
- fixed DataFrame methods rownames() and colnames()
doc:
- more editing of the documentation
Modified Paths:
--------------
branches/rpy_nextgen/NEWS
branches/rpy_nextgen/doc/source/overview.rst
branches/rpy_nextgen/doc/source/rinterface.rst
branches/rpy_nextgen/doc/source/rlike.rst
branches/rpy_nextgen/doc/source/robjects.rst
branches/rpy_nextgen/rpy/rinterface/rinterface.c
branches/rpy_nextgen/rpy/rinterface/tests/test_Sexp.py
branches/rpy_nextgen/rpy/rlike/indexing.py
branches/rpy_nextgen/rpy/robjects/__init__.py
Modified: branches/rpy_nextgen/NEWS
===================================================================
--- branches/rpy_nextgen/NEWS 2008-08-24 13:47:05 UTC (rev 640)
+++ branches/rpy_nextgen/NEWS 2008-08-25 07:08:15 UTC (rev 641)
@@ -14,6 +14,10 @@
- method :meth:`rsame` to test if the underlying R objects for two
:class:`Sexp` are the same.
+- added `emptyEnv` (R's C-level `R_EmptyEnv`)
+
+- added method :meth:`Sexp.do_slot_assign`
+
:mod:`rpy2.robjects`:
- R string vectors can now be built from Python unicode objects
@@ -42,6 +46,7 @@
- R objects of type EXPRSXP are now handled as vectors (... but this may
change again)
+
:mod:`rpy2.robjects`:
- :class:`R` remains a singleton, but does not throw an exception when
multiple instances are requested
@@ -64,6 +69,7 @@
- complex vectors should now be handled properly by
:mod:`rpy2.rinterface.robjects`.
+- methods :meth:`rownames` and :meth:`colnames` for :class:`RDataFrame` were
incorrect.
Release 2.0.0a2
===============
Modified: branches/rpy_nextgen/doc/source/overview.rst
===================================================================
--- branches/rpy_nextgen/doc/source/overview.rst 2008-08-24 13:47:05 UTC
(rev 640)
+++ branches/rpy_nextgen/doc/source/overview.rst 2008-08-25 07:08:15 UTC
(rev 641)
@@ -139,10 +139,11 @@
- the use of the module simple from both a Python or R user's perspective
-- minimize the need for knowledge about R, and the need for tricks are
workaround.
-- the possibility to customize a lot only with Python (without having to go to
C-level).
+- minimize the need for knowledge about R, and the need for tricks and
workarounds.
+- the possibility to customize a lot while remaining at the Python level
(without having to go down to C-level).
+
:mod:`rpy2.robjects` implements an extension to the interface in
:mod:`rpy2.rinterface` by extending the classes for R
objects defined there with child classes.
Modified: branches/rpy_nextgen/doc/source/rinterface.rst
===================================================================
--- branches/rpy_nextgen/doc/source/rinterface.rst 2008-08-24 13:47:05 UTC
(rev 640)
+++ branches/rpy_nextgen/doc/source/rinterface.rst 2008-08-25 07:08:15 UTC
(rev 641)
@@ -222,7 +222,7 @@
called :meth:`do_slot` in the C interface to R.
:param name: string
- :rtype: Sexp (or Sexp-inheriting) object
+ :rtype: instance of :class:`Sexp`
>>> matrix = rinterface.globalEnv.get("matrix")
>>> letters = rinterface.globalEnv.get("letters")
@@ -232,6 +232,14 @@
[13, 2]
>>>
+ .. method:: do_slot_assign(name, value)
+
+ Assign value to the slot with the given name
+
+ :param name: string
+ :param value: instance of :class:`Sexp`
+
+
.. method:: rsame(sexp_obj)
Tell whether the underlying R object for sexp_obj is the same or not.
@@ -523,10 +531,9 @@
def rsearch():
""" Return a list of package environments corresponding to the
R search path. """
- emptyenv = ri.baseNameSpaceEnv.get('emptyenv')()
spath = [ri.globalEnv, ]
item = ri.globalEnv.enclos()
- while not item.rsame(emptyenv):
+ while not item.rsame(ri.emptyEnv):
spath.append(item)
item = item.enclos()
spath.append(ri.baseNameSpaceEnv)
@@ -541,7 +548,6 @@
def wherefrom(name, startenv=ri.globalEnv):
""" when calling 'get', where the R object is coming from. """
- emptyenv = ri.baseNameSpaceEnv.get('emptyenv')()
env = startenv
obj = None
retry = True
@@ -551,7 +557,7 @@
retry = False
except LookupError, knf:
env = env.enclos()
- if env.rsame(emptyenv):
+ if env.rsame(ri.emptyEnv):
retry = False
else:
retry = True
@@ -723,6 +729,9 @@
:const:`LANGSXP`
Language object.
+:const:`EXPRSXP`
+ Unevaluated expression.
+
Other types
^^^^^^^^^^^
@@ -736,7 +745,7 @@
Instance of class S4. Represented by :class:`rpy2.rinterface.SexpS4`.
-Types you should not meet
+Types one should not meet
^^^^^^^^^^^^^^^^^^^^^^^^^
:const:`PROMSXP`
Modified: branches/rpy_nextgen/doc/source/rlike.rst
===================================================================
--- branches/rpy_nextgen/doc/source/rlike.rst 2008-08-24 13:47:05 UTC (rev
640)
+++ branches/rpy_nextgen/doc/source/rlike.rst 2008-08-25 07:08:15 UTC (rev
641)
@@ -96,21 +96,52 @@
.. autoclass:: rpy2.rlike.container.TaggedList
:members:
+
+.. module:: rpy2.rlike.functional
+
Tools for working with sequences
================================
-.. autofunction:: rpy2.rlike.functional.tapply
+.. autofunction:: tapply
>>> import rpy2.rlike.functional as rlf
>>> rlf.tapply((1,2,3), ('a', 'b', 'a'), sum)
[('a', 4), ('b', 2)]
+.. module:: rpy2.rlike.indexing
+
Indexing
========
-.. function:: rpy2.rlike.indexing.order
+Much of the R-style indexing can be achieved with Python's list comprehension:
+>>> x = ('a', 'b', 'c')
+>>> x_i = (0, 2)
+>>> [x[i] for i in x_i]
+['a', 'c']
+
+In `R`, negative indexes mean that values should be excluded. Again,
+list comprehension can be used:
+
+>>> x = ('a', 'b', 'c')
+>>> x_i = (0, 2)
+
+.. function:: order(seq, cmp = default_cmp, reverse = False)
+
+ Give the order in which to take the items in the sequence `seq` and
+ have them sorted.
+ The optional function cmp should return +1, -1, or 0.
+
+ :param seq: sequence
+ :param cmp: function
+ :param reverse: boolean
+ :rtype: list of integers
+
>>> import rpy2.rlike.indexing as rli
->>> rli.order(('a', 'c', 'b'))
+>>> x = ('a', 'c', 'b')
+>>> o = rli.order(x)
+>>> o
[0, 2, 1]
+>>> [x[i] for i in o]
+['a', 'b', 'c']
\ No newline at end of file
Modified: branches/rpy_nextgen/doc/source/robjects.rst
===================================================================
--- branches/rpy_nextgen/doc/source/robjects.rst 2008-08-24 13:47:05 UTC
(rev 640)
+++ branches/rpy_nextgen/doc/source/robjects.rst 2008-08-25 07:08:15 UTC
(rev 641)
@@ -257,6 +257,7 @@
:show-inheritance:
:members:
+
Environments
============
@@ -304,7 +305,11 @@
>>> env = robjects.r.baseenv()
>>> len([x for x in env])
+<a long list returned>
+For further information, read the documentation for the
+class :class:`rpy2.rinterface.SexpEnvironment`.
+
.. index::
pair: robjects; RFunction
pair: robjects; function
Modified: branches/rpy_nextgen/rpy/rinterface/rinterface.c
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-08-24 13:47:05 UTC
(rev 640)
+++ branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-08-25 07:08:15 UTC
(rev 641)
@@ -138,6 +138,7 @@
static PySexpObject *globalEnv;
static PySexpObject *baseNameSpaceEnv;
+static PySexpObject *emptyEnv;
static PySexpObject *na_string;
/* early definition of functions */
@@ -363,6 +364,7 @@
RPY_SEXP(globalEnv) = R_GlobalEnv;
RPY_SEXP(baseNameSpaceEnv) = R_BaseNamespace;
+ RPY_SEXP(emptyEnv) = R_EmptyEnv;
RPY_SEXP(na_string) = NA_STRING;
GetErrMessage_SEXP = findVar(install("geterrmessage"),
@@ -406,6 +408,7 @@
RPY_SEXP(globalEnv) = R_EmptyEnv;
RPY_SEXP(baseNameSpaceEnv) = R_EmptyEnv;
+ RPY_SEXP(emptyEnv) = R_EmptyEnv;
GetErrMessage_SEXP = R_NilValue;
//FIXME: Is it possible to reinitialize R later ?
@@ -547,6 +550,50 @@
":rtype: instance of type or subtype
:class:`rpy2.rinterface.Sexp`");
static PyObject*
+Sexp_do_slot_assign(PyObject *self, PyObject *args)
+{
+
+ SEXP sexp = RPY_SEXP(((PySexpObject*)self));
+ if (! sexp) {
+ PyErr_Format(PyExc_ValueError, "NULL SEXP.");
+ return NULL;;
+ }
+
+ char *name_str;
+ PyObject *value;
+ if (! PyArg_ParseTuple(args, "sO",
+ &name_str,
+ &value)) {
+ return NULL;
+ }
+
+ if (! PyObject_IsInstance(value,
+ (PyObject*)&Sexp_Type)) {
+ PyErr_Format(PyExc_ValueError, "Value must be an instance of Sexp.");
+ return NULL;
+ }
+
+ if (! R_has_slot(sexp, install(name_str))) {
+ PyErr_SetString(PyExc_LookupError, "The object has no such attribute.");
+ return NULL;
+ }
+ SEXP value_sexp = RPY_SEXP((PySexpObject *)value);
+ if (! value_sexp) {
+ PyErr_Format(PyExc_ValueError, "NULL SEXP.");
+ return NULL;;
+ }
+
+ SET_SLOT(sexp, install(name_str), value_sexp);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+PyDoc_STRVAR(Sexp_do_slot_assign_doc,
+ "Set the attribute/slot for an R object.\n"
+ "\n"
+ ":param name: string\n"
+ ":param value: instance of rpy2.rinterface.Sexp");
+
+static PyObject*
Sexp_named_get(PyObject *self)
{
SEXP sexp = RPY_SEXP(((PySexpObject*)self));
@@ -563,7 +610,7 @@
See the R-extensions manual for further details.");
static PyObject*
-Sexp_sexp_get(PyObject *self)
+Sexp_sexp_get(PyObject *self, void *closure)
{
SEXP sexp = RPY_SEXP(((PySexpObject*)self));
@@ -575,6 +622,23 @@
PyObject *res = PyCObject_FromVoidPtr(sexp, NULL);
return res;
}
+
+/* static PyObject* */
+/* Sexp_sexp_set(PyObject *self, PyObject *obj, void *closure) */
+/* { */
+/* if (! PyCObject_Check(obj)) { */
+/* PyErr_SetString(PyExc_TypeError, "The value must be a CObject."); */
+/* return -1; */
+/* } */
+/* SEXP sexp = (SEXP) PyCObject_AsVoidPtr(PyObject* obj); */
+/* if (! sexp) { */
+/* PyErr_Format(PyExc_ValueError, "NULL SEXP."); */
+/* return -1; */
+/* } */
+/* RPY_SEXP(((PySexpObject*)self)) = sexp; */
+
+/* return 0; */
+/* } */
PyDoc_STRVAR(Sexp_sexp_doc,
"Opaque C pointer to the underlying R object");
@@ -611,6 +675,8 @@
static PyMethodDef Sexp_methods[] = {
{"do_slot", (PyCFunction)Sexp_do_slot, METH_O,
Sexp_do_slot_doc},
+ {"do_slot_assign", (PyCFunction)Sexp_do_slot_assign, METH_VARARGS,
+ Sexp_do_slot_assign_doc},
{"rsame", (PyCFunction)Sexp_rsame, METH_O,
Sexp_rsame_doc},
{NULL, NULL} /* sentinel */
@@ -2501,6 +2567,12 @@
/* //FIXME: DECREF ? */
/* Py_DECREF(baseNameSpaceEnv); */
+ emptyEnv = (PySexpObject*)Sexp_new(&EnvironmentSexp_Type,
+ Py_None, Py_None);
+ RPY_SEXP(emptyEnv) = R_EmptyEnv;
+ if (PyDict_SetItemString(d, "emptyEnv",
+ (PyObject *)emptyEnv) < 0)
+ return;
/* Add SXP types */
validSexpType = calloc(maxValidSexpType, sizeof(char *));
Modified: branches/rpy_nextgen/rpy/rinterface/tests/test_Sexp.py
===================================================================
--- branches/rpy_nextgen/rpy/rinterface/tests/test_Sexp.py 2008-08-24
13:47:05 UTC (rev 640)
+++ branches/rpy_nextgen/rpy/rinterface/tests/test_Sexp.py 2008-08-25
07:08:15 UTC (rev 641)
@@ -50,8 +50,17 @@
for i, n in enumerate(iris_names):
self.assertEquals(iris_names[i], names[i])
- self.assertRaises(LookupError, sexp.do_slot, "foo")
+ self.assertRaises(LookupError, sexp.do_slot, "foo")
+ def testDo_slot_assign(self):
+ data_func = rinterface.globalEnv.get("data")
+ data_func(rinterface.SexpVector(["iris", ], rinterface.STRSXP))
+ sexp = rinterface.globalEnv.get("iris")
+ iris_names = rinterface.StrSexpVector(['a', 'b', 'c', 'd', 'e'])
+ sexp.do_slot_assign("names", iris_names)
+ names = [x for x in sexp.do_slot("names")]
+ self.assertEquals(['a', 'b', 'c', 'd', 'e'], names)
+
def testSexp_rsame_true(self):
sexp_a = rinterface.globalEnv.get("letters")
sexp_b = rinterface.globalEnv.get("letters")
Modified: branches/rpy_nextgen/rpy/rlike/indexing.py
===================================================================
--- branches/rpy_nextgen/rpy/rlike/indexing.py 2008-08-24 13:47:05 UTC (rev
640)
+++ branches/rpy_nextgen/rpy/rlike/indexing.py 2008-08-25 07:08:15 UTC (rev
641)
@@ -1,17 +1,24 @@
-def order(sortable, reverse = False):
- o = range(len(sortable))
- def cmp(x, y):
- x = sortable[x]
- y = sortable[y]
- if x < y:
- return -1
- elif x > y:
- return +1
- else:
- return 0
+def default_cmp(x, y):
+ """ Default comparison function """
+ if x < y:
+ return -1
+ elif x > y:
+ return +1
+ else:
+ return 0
+
+def order(seq, cmp = default_cmp, reverse = False):
+ """ Return the order in which to take the items to obtained
+ a sorted sequence."""
+ o = range(len(seq))
+
+ def wrap_cmp(x, y):
+ x = seq[x]
+ y = seq[y]
+ return cmp(x, y)
- o.sort(cmp = cmp, reverse = reverse)
+ o.sort(cmp = wrap_cmp, reverse = reverse)
return o
Modified: branches/rpy_nextgen/rpy/robjects/__init__.py
===================================================================
--- branches/rpy_nextgen/rpy/robjects/__init__.py 2008-08-24 13:47:05 UTC
(rev 640)
+++ branches/rpy_nextgen/rpy/robjects/__init__.py 2008-08-25 07:08:15 UTC
(rev 641)
@@ -54,7 +54,6 @@
res = RObject(o)
return res
-#FIXME: better names for the functions
ri2py = default_ri2py
@@ -350,20 +349,23 @@
def rownames(self):
""" Row names
- :rype: SexpVector
+
+ :rtype: SexpVector
"""
- return baseNameSpaceEnv["colnames"](self)[0]
+ res = baseNameSpaceEnv["rownames"](self)
+ return ri2py(res)
def colnames(self):
""" Column names
- :rype: SexpVector
+
+ :rtype: SexpVector
"""
- return baseNameSpaceEnv["colnames"](self)[0]
+ res = baseNameSpaceEnv["colnames"](self)
+ return ri2py(res)
-
class RFunction(RObjectMixin, rinterface.SexpClosure):
- """ An R function (aka "closure").
+ """ An R function.
"""
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
rpy-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rpy-list