<commit_before>import socket, time
###
import rtypes
from rexceptions import RConnectionRefused, REvalError, PyRserveClosed
from rserializer import rEval, rAssign
from rparser import rparse

RSERVEPORT = 6311
DEBUG = False


def rconnect(host='', port=RSERVEPORT):
#    if host in (None, ''):
#        # On Win32 it seems that passing an empty string as 'localhost' does not work
#        # So just to be sure provide the full local hostname if None or '' were passed.
#        host = socket.gethostname()
    assert port is not None, 'port number must be given'
    return RConnector(host, port)


def checkIfClosed(func):
    def decoCheckIfClosed(self, *args, **kw):
        if self.isClosed:
            raise PyRserveClosed('Connection to Rserve already closed')
        return func(self, *args, **kw)
    return decoCheckIfClosed
    


class RConnector(object):
    '@brief Provides a network connector to an Rserve process'
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.connect()
        self.r = RNameSpace(self)
        self.ref = RNameSpaceReference(self)
        
    def __repr__(self):
        txt = 'Closed handle' if self.isClosed else 'Handle'
        return '<%s to Rserve on %s:%s>' % (txt, self.host or 'localhost', self.port)

    @property
    def isClosed(self):
        return self.__closed

    def connect(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.sock.connect((self.host, self.port))
        except socket.error:
            raise RConnectionRefused('Connection denied, server not reachable or not accepting connections')
        time.sleep(0.2)
        hdr = self.sock.recv(1024)
        self.__closed = False
        if DEBUG:
            print 'received hdr %s from rserve' % hdr
        assert hdr.startswith('Rsrv01') # make sure we are really connected with rserv
        # TODO: possibly also do version checking here to make sure we understand the protocol...

    @checkIfClosed
    def close(self):
        '@brief Close network connection to rserve'
        self.sock.close()
        self.__closed = True
        
    @checkIfClosed
    def __call__(self, aString):
        return self.eval(aString)
        
    @checkIfClosed
    def eval(self, aString):
        '@brief Evaluate a string expression through Rserve and return the result transformed into python objects'
        if type(aString) != str:
            raise TypeError('Only string evaluation is allowed')
        rEval(aString, fp=self.sock)
        if DEBUG:
            # Read entire data into memory en block, it's easier to debug
            src = self.receive()
            print 'Raw response:', repr(src)
        else:
            src = self.sock.makefile()
        return rparse(src)
        
    @checkIfClosed
    def send(self, *args, **kw):
        '''
        @brief Serializes given arguments and sends them to the rserve process.
        @note  The result needs to be received separately (using self.receive())
        '''
        data = rserialize(args[0] if len(args)==1 else args, **kw)
        self.sock.send(data)

    @checkIfClosed
    def receive(self):
        '@brief Receive the result from a previous call to rserve.'
        raw = self.sock.recv(rtypes.SOCKET_BLOCK_SIZE)
        d = [raw]
        while len(raw) == rtypes.SOCKET_BLOCK_SIZE:
            raw = self.sock.recv(rtypes.SOCKET_BLOCK_SIZE)
            d.append(raw)
        return ''.join(d)

    @checkIfClosed
    def raw(self, *args, **kw):
        self.send(*args)
        return self.receive()

    @checkIfClosed
    def setRexp(self, name, o):
        '@brief Convert a python object into an RExp and bind it to a variable called "name" in the R namespace'
        rAssign(name, o, self.sock)
        # Rserv sends an emtpy confirmation message, or error message in case of an error.
        # rparse() will raise an Exception in the latter case.
        rparse(self.sock)

    @checkIfClosed
    def getRexp(self, name):
        '@brief Retrieve a Rexp stored in a variable called "name"'
        return self.eval(name)
        
    @checkIfClosed
    def callFunc(self, name, *args, **kw):
        '''
        @brief  make a call to a function "name" through Rserve
        @detail positional and keyword arguments are first stored as local variables in 
                the R namespace and then delivered to the function.
        @result Whatever the result of the called function is.
        '''
        if name == 'rm':
            # SPECIAL HANDLING FOR "rm()":
            # Calling "rm" with real values instead of reference to values works, however
            # it doesn't produce the desired effect (it only removes our temporaily created
            # variables). To avoid confusion for the users a check is applied here to make<commit_msg>minor change<commit_after>import socket, time
###
import rtypes
from rexceptions import RConnectionRefused, REvalError, PyRserveClosed
from rserializer import rEval, rAssign
from rparser import rparse

RSERVEPORT = 6311
DEBUG = False


def rconnect(host='', port=RSERVEPORT):
#    if host in (None, ''):
#        # On Win32 it seems that passing an empty string as 'localhost' does not work
#        # So just to be sure provide the full local hostname if None or '' were passed.
#        host = socket.gethostname()
    assert port is not None, 'port number must be given'
    return RConnector(host, port)


def checkIfClosed(func):
    def decoCheckIfClosed(self, *args, **kw):
        if self.isClosed:
            raise PyRserveClosed('Connection to Rserve already closed')
        return func(self, *args, **kw)
    return decoCheckIfClosed
    


class RConnector(object):
    '@brief Provides a network connector to an Rserve process'
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.connect()
        self.r = RNameSpace(self)
        self.ref = RNameSpaceReference(self)
        
    def __repr__(self):
        txt = 'Closed handle' if self.isClosed else 'Handle'
        return '<%s to Rserve on %s:%s>' % (txt, self.host or 'localhost', self.port)

    @property
    def isClosed(self):
        return self.__closed

    def connect(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.sock.connect((self.host, self.port))
        except socket.error:
            raise RConnectionRefused('Connection denied, server not reachable or not accepting connections')
        time.sleep(0.2)
        hdr = self.sock.recv(1024)
        self.__closed = False
        if DEBUG:
            print 'received hdr %s from rserve' % hdr
        assert hdr.startswith('Rsrv01') # make sure we are really connected with rserv
        # TODO: possibly also do version checking here to make sure we understand the protocol...

    @checkIfClosed
    def close(self):
        '@brief Close network connection to rserve'
        self.sock.close()
        self.__closed = True
        
    @checkIfClosed
    def __call__(self, aString):
        return self.eval(aString)
        
    @checkIfClosed
    def eval(self, aString):
        '@brief Evaluate a string expression through Rserve and return the result transformed into python objects'
        if type(aString) != str:
            raise TypeError('Only string evaluation is allowed')
        rEval(aString, fp=self.sock)
        if DEBUG:
            # Read entire data into memory en block, it's easier to debug
            src = self.receive()
            print 'Raw response:', repr(src)
        else:
            src = self.sock.makefile()
        return rparse(src)
        
#    @checkIfClosed
#    def send(self, *args, **kw):
#        '''
#        @brief Serializes given arguments and sends them to the rserve process.
#        @note  The result needs to be received separately (using self.receive())
#        '''
#        data = rserialize(args[0] if len(args)==1 else args, **kw)
#        self.sock.send(data)
#
#    @checkIfClosed
#    def receive(self):
#        '@brief Receive the result from a previous call to rserve.'
#        raw = self.sock.recv(rtypes.SOCKET_BLOCK_SIZE)
#        d = [raw]
#        while len(raw) == rtypes.SOCKET_BLOCK_SIZE:
#            raw = self.sock.recv(rtypes.SOCKET_BLOCK_SIZE)
#            d.append(raw)
#        return ''.join(d)
#
#    @checkIfClosed
#    def raw(self, *args, **kw):
#        self.send(*args)
#        return self.receive()

    @checkIfClosed
    def setRexp(self, name, o):
        '@brief Convert a python object into an RExp and bind it to a variable called "name" in the R namespace'
        rAssign(name, o, self.sock)
        # Rserv sends an emtpy confirmation message, or error message in case of an error.
        # rparse() will raise an Exception in the latter case.
        rparse(self.sock)

    @checkIfClosed
    def getRexp(self, name):
        '@brief Retrieve a Rexp stored in a variable called "name"'
        return self.eval(name)
        
    @checkIfClosed
    def callFunc(self, name, *args, **kw):
        '''
        @brief  make a call to a function "name" through Rserve
        @detail positional and keyword arguments are first stored as local variables in 
                the R namespace and then delivered to the function.
        @result Whatever the result of the called function is.
        '''
        if name == 'rm':
            # SPECIAL HANDLING FOR "rm()":
            # Calling "rm" with real values instead of reference to values works, however
            # it doesn't produce the desired effect (it only removes our temporaily created
            # variables). To avoid confusion for the users a check is applied here to make
{'fraction_non_alphanumeric': 0.08903688524590164, 'fraction_numerical': 0.003278688524590164, 'mean_word_length': 2.3751728907330567, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3780207', 'n_tokens_mistral': 2794, 'n_tokens_neox': 2704, 'n_words': 1000}