# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # High level module for managing the lookup of R objects. # # $Id: rpy.py,v 1.9 2004/02/04 21:26:46 warnes Exp $ # # from __future__ import nested_scopes import rpy_io import UserDict import time, os, sys # If we cannot import Numeric, it should have been detected at # installation time and RPy should have been compiled properly. So, # don't complain. try: from Numeric import * except ImportError: pass # try to import rpy binary library using current path try: import _rpy except ImportError: if sys.platform == 'win32': import win32api, win32con hkey = win32api.RegOpenKeyEx( win32con.HKEY_LOCAL_MACHINE, "Software\\R-core\\R", 0, win32con.KEY_QUERY_VALUE ) # get the base directory rpath = win32api.RegQueryValueEx( hkey, "InstallPath" )[0] win32api.RegCloseKey( hkey ) Rlib = os.path.join( rpath, 'bin', 'R.dll') # Now, load the library into the python address space and retry the # import win32api.LoadLibraryEx( Rlib, 0, win32con.LOAD_WITH_ALTERED_SEARCH_PATH ) import _rpy else: raise # Version from rpy_version import rpy_version # Symbolic names for conversion modes PROC_CONVERSION = 3 CLASS_CONVERSION = 2 BASIC_CONVERSION = 1 NO_CONVERSION = 0 NO_DEFAULT = -1 # Wrap a function in safe modes to avoid infinite recursion when # called from within the conversion system def with_mode(i, fun): def f(*args, **kwds): try: e = get_default_mode() set_default_mode(i) return fun(*args, **kwds) finally: set_default_mode(e) return f # Manage the global mode def set_default_mode(mode): _rpy.set_mode(mode) def get_default_mode(): return _rpy.get_mode() # The new exception RException = _rpy.RException # I/O setters set_rpy_output = _rpy.set_output set_rpy_input = _rpy.set_input get_rpy_output = _rpy.get_output get_rpy_input = _rpy.get_input if sys.platform != 'win32': set_rpy_showfiles = _rpy.set_showfiles get_rpy_showfiles = _rpy.get_showfiles # Default I/O to functions in the 'rpy_io' module set_rpy_output(rpy_io.rpy_output) set_rpy_input(rpy_io.rpy_input) if sys.platform != 'win32': set_rpy_showfiles(rpy_io.rpy_showfiles) # Functions for processing events import threading r_events = _rpy.r_events _r_thread = None _r_events_running = threading.Event() _r_lock = threading.Lock() def r_eventloop(): while _r_events_running.isSet(): _r_lock.acquire() r_events() _r_lock.release() time.sleep(0.2) def start_r_eventloop(): global _r_thread if _r_thread and _r_thread.isAlive(): return _r_thread = threading.Thread(target=r_eventloop) _r_thread.setDaemon(1) _r_events_running.set() _r_thread.start() return _r_thread def stop_r_eventloop(): _r_events_running.clear() if sys.platform != 'win32': start_r_eventloop() # This function unifies the case of results of length one, which RPy # returns as single values, and results of length greater than one, # which are lists. def as_list(obj): try: obj+[] return obj except: return [obj] # A special dict to wrap the arguments in safe modes. It would be # easier with 2.2, subclassing directly from type 'dict'. class Dict_With_Mode(UserDict.UserDict): def __init__(self, initialdata): self.data = initialdata def __setitem__(self, key, value): val = with_mode(BASIC_CONVERSION, value) if type(key) in [type(''), type(())]: self.data[key] = val else: self.data[with_mode(BASIC_CONVERSION, key)] = val # Tables for {PROC,CLASS}_CONVERSION modes class_table = Dict_With_Mode(_rpy.__class_table__) proc_table = Dict_With_Mode(_rpy.__proc_table__) # main class class R: def __init__(self): _rpy.set_mode(NO_DEFAULT) self.TRUE = self.__getitem__('T') self.FALSE = self.__getitem__('F') def __getattr__(self, name): if len(name) > 1 and name[-1] == '_' and name[-2] != '_': name = name[:-1] name = name.replace('__', '<-') name = name.replace('_', '.') return self.__getitem__(name) def __getitem__(self, name): obj = self.__dict__[name] = self.__dict__.get(name, _rpy.get(name)) return obj def __call__(self, s): return r.eval(r.parse(text=s)) # main instance r = R() # disable the printing of errors from within R r.options(show_error_messages=0) # That's all...