All Downloads are FREE. Search and download functionalities are using the official Maven repository.

thon.2.7-b1.source-code.test_jython_readline_isue.py Maven / Gradle / Ivy

Go to download

Jython is an implementation of the high-level, dynamic, object-oriented language Python written in 100% Pure Java, and seamlessly integrated with the Java platform. It thus allows you to run Python on any Java platform.

There is a newer version: 2.7.4
Show newest version
#!/usr/bin/python

import errno
import fcntl
import os
import select
import socket
import subprocess
import sys


# Works:
#_REMOTE_CMD = ["cat"]

# Works (NOTE: this cmd is python, not jython!)
#_REMOTE_CMD = ["python", "-c", "import sys; sys.stdout.write(sys.stdin.readline()); sys.stdout.flush();"]

# Doesn't work with jython 2.5.3 (but works fine with jython 2.5.2)
_REMOTE_CMD = ["./dist/bin/jython", "-c", "import sys; sys.stdout.write(sys.stdin.readline()); sys.stdout.flush();"]


def _testAll():
  for name in sorted(g_cmds.keys()):
    
    func = g_cmds[name]
    
    if func is not _testAll:
      func()


def _testBlockingViaFile():
  print >> sys.stderr, ("\n"
    "Testing blocking write/read via file API")
  
  p = _createSubprocess(_REMOTE_CMD)
  
  dataIn = "f"*55 + "\n"
  p.stdin.write(dataIn)
  p.stdin.flush()
  
  dataOut = p.stdout.read(len(dataIn))
  
  print repr(dataOut)
  
  assert dataOut == dataIn, "%r != %r" % (dataOut, dataIn)
  
  p.stdin.close()
  p.wait()
  
  print "ok"
  return


def _testBlockingViaFD():
  print >> sys.stderr, ("\n"
    "Testing blocking write/read via fd")
  
  p = _createSubprocess(_REMOTE_CMD)
  
  w = p.stdin.fileno()
  r = p.stdout.fileno()
  
  dataIn = "d"*55 + "\n"
  
  os.write(w, dataIn)
  
  dataOut = os.read(r, len(dataIn))
  
  print repr(dataOut)
  
  assert dataOut == dataIn, "%r != %r" % (dataOut, dataIn)
  
  p.stdin.close()
  p.wait()
  
  print "ok"
  return


def _testNonBlockingViaFDPolling():
  print >> sys.stderr, ("\n"
    "Testing NON-BLOCKING write/read via fd/POLLING")
  
  p = _createSubprocess(_REMOTE_CMD)
  
  w = p.stdin.fileno()
  r = p.stdout.fileno()
  
  wOldFlags = _getFCNTLFlags(w)
  print "w-fd initial FCNTL flags:", wOldFlags
  rOldFlags = _getFCNTLFlags(r)
  print "r-fd initial FCNTL flags:", rOldFlags
  
  _applyFCNTLFlags(w, os.O_NONBLOCK)
  wNewFlags = _getFCNTLFlags(w)
  print "w-fd FCNTL flags after w+=O_NONBLOCK:", _getFCNTLFlags(w)
  print "r-fd FCNTL flags after w+=O_NONBLOCK:", _getFCNTLFlags(r)
  assert _getFCNTLFlags(r) == rOldFlags
  
  _applyFCNTLFlags(r, os.O_NONBLOCK)
  print "w-fd FCNTL flags after r+=O_NONBLOCK:", _getFCNTLFlags(w)
  print "r-fd FCNTL flags after r+=O_NONBLOCK:", _getFCNTLFlags(r)
  assert _getFCNTLFlags(w) == wNewFlags
  
  
  dataIn = "P"*55 + "\n"
  
  savedFlags = _applyFCNTLFlags(w, os.O_NONBLOCK)
  try:
    numBytesWritten = os.write(w, dataIn)
  finally:
    _replaceFCNTLFlags(w, savedFlags)
  print "numBytesWritten:", numBytesWritten
  
  dataOut = ""
  while True:
    try:
      dataOut += os.read(r, numBytesWritten)
    except OSError, e:
      if e.errno != errno.EAGAIN:
        raise
      
      if dataOut:
        break
      else:
        continue
  
  numBytesRead = len(dataOut)
  print "numBytesRead: ", numBytesRead
  
  print repr(dataOut)
  
  assert dataOut == dataIn, "%r != %r" % (dataOut, dataIn)
  
  p.stdin.close()
  p.wait()
  
  print "ok"
  return


def _testNonBlockingViaFDSelect():
  print >> sys.stderr, ("\n"
    "Testing NON-BLOCKING write/read via fd/SELECT")
  
  p = _createSubprocess(_REMOTE_CMD)
  
  w = p.stdin.fileno()
  r = p.stdout.fileno()
  
  wOldFlags = _getFCNTLFlags(w)
  print "w-fd initial FCNTL flags:", wOldFlags
  rOldFlags = _getFCNTLFlags(r)
  print "r-fd initial FCNTL flags:", rOldFlags
  
  _applyFCNTLFlags(w, os.O_NONBLOCK)
  wNewFlags = _getFCNTLFlags(w)
  print "w-fd FCNTL flags after w+=O_NONBLOCK:", _getFCNTLFlags(w)
  print "r-fd FCNTL flags after w+=O_NONBLOCK:", _getFCNTLFlags(r)
  assert _getFCNTLFlags(r) == rOldFlags
  
  reader = FDLineReader(r)
  print "w-fd FCNTL flags after FDLineReader(r):", _getFCNTLFlags(w)
  print "r-fd FCNTL flags after FDLineReader(r):", _getFCNTLFlags(r)
  assert _getFCNTLFlags(w) == wNewFlags
  
  
  dataIn = "S"*55 + "\n"
  
  fdWriteString(w, dataIn)
  
  dataOut = reader.readline()
  
  numBytesRead = len(dataOut)
  print "numBytesRead: ", numBytesRead
  
  print repr(dataOut)
  
  assert dataOut == dataIn, "%r != %r" % (dataOut, dataIn)
  
  p.stdin.close()
  p.wait()
  
  print "ok"
  return


def _createSubprocess(args):
  kwargs = dict(
    bufsize=-1,
    stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None,
    close_fds=True,
    shell=False,
    universal_newlines=False    
  )
  return subprocess.Popen(args, **kwargs)


###############################################################################
class FDLineReader(object):
  """ Read a line of text from a file descriptor up to and including the very
  first '\n', using select.select to wait for input.
  """
  
  def __init__(self, fd):
    """ Construct the reader; configure the given file descriptor for
    non-blocking operation
    
    fd:             The input file-descriptor; WARNING: don't mix use of
                     buffered (e.g., sys.stdin.read()) I/O with
                     file-descriptor-based I/O (e.g.,
                     os.read(sys.stdin.fileno()))
    makeNonBlocking:
                    If True, the given file-descriptor will be configured for
                     non-blocking IO;
                     WARNING: if the fd is from sys.stdin.fileno(),
                     then changing this fd to non-blocking also has the side-
                     effect of making the file desriptor in sys.stdout
                     non-blocking, so print and sys.stdout.write/flush will
                     sometimes fail with "IOError: [Errno 35] Resource
                     temporarily unavailable" (35=errno.EWOULDBLOCK).
    """
    
    fcntl.fcntl(fd, fcntl.F_SETFL,
                fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
    
    self._fd = fd
    
    return
  
  
  def readline(self):
    """ Read a line of text from a file descriptor up to and including the very
    first '\n'
    
    NOTE: Lines are assumed to be terminated with '\n'
    """
    
    fd = self._fd
    
    data = ""
    
    rlist = [fd]
    wlist = xlist = []
    
    while not data.endswith('\n'):
      rready = select.select(rlist, wlist, xlist)[0]
      assert fd in rready
      
      # Read 
      newData = ""
      while newData != '\n':
        try:
          newData = os.read(fd, 1024)
        except (OSError, socket.error), e:
          if e.args[0] != errno.EWOULDBLOCK:
            raise
          
          # EWOULDBLOCK: we'll wait in outer loop's select for more data
          break
        else:
          if not newData:
            # EOF reached
            return data
          
          data += newData
          
    
    return data



###############################################################################
def fdWriteString(fd, string):
  """ Write the given string to a file descriptor, using select.select to wait
  for input.
  """
  if isinstance(string, unicode):
    string = string.encode()
  
  wlist = [fd]
  rlist = xlist = []
  
  bytesToSend = len(string)
  numBytesSent = 0
  
  while numBytesSent < bytesToSend:
    wready = select.select(rlist, wlist, xlist)[1]
    assert fd in wready
    
    originalFdFlags = _applyFCNTLFlags(fd, os.O_NONBLOCK)
    try:
      numBytesSent += os.write(fd, buffer(string, numBytesSent))
    except (OSError, socket.error), e:
      if e.args[0] != errno.EWOULDBLOCK:
        raise
    finally:
      _replaceFCNTLFlags(fd, originalFdFlags)
  
  return



def _getFCNTLFlags(fd):
  return fcntl.fcntl(fd, fcntl.F_GETFL)

def _replaceFCNTLFlags(fd, flags):
  oldFlags = _getFCNTLFlags(fd)
  fcntl.fcntl(fd, fcntl.F_SETFL, flags)
  return oldFlags

def _applyFCNTLFlags(fd, mixInFlags):
  oldFlags = _getFCNTLFlags(fd)
  fcntl.fcntl(fd, fcntl.F_SETFL, oldFlags | mixInFlags)
  
  return oldFlags



g_cmds = {
  "all" : _testAll,
  "cat-block" : _testBlockingViaFile,
  "cat-fdblock" : _testBlockingViaFD,
  "cat-fdpollnoblock" : _testNonBlockingViaFDPolling,
  "cat-fdselectnoblock" : _testNonBlockingViaFDSelect,
}


def main():
  
  
  def argErrorAndHelpAndExit(cmd=None):
    if cmd is not None:
      print "Unknown command: ", cmd
      
    print "Supported commands:", ", ".join(sorted(g_cmds.keys()))
    sys.exit(1)
    
  
  try:
    func = g_cmds[sys.argv[1]]
  except IndexError:
    argErrorAndHelpAndExit()
  except KeyError:
    argErrorAndHelpAndExit(sys.argv[1])

  print "_REMOTE_CMD:", " ".join(_REMOTE_CMD)
  
  func()



if __name__ == '__main__':
  main()




© 2015 - 2024 Weber Informatics LLC | Privacy Policy