# Path: ayrton/utils.py
# def copy_loop (copy_to, finished=None, buf_len=10240):
#     """copy_to is a dict(in: out). When any in is ready to read, data is read
#     from it and writen in its out. When any in is closed, it's removed from
#     copy_to. finished is a pipe; when data comes from the read end, or when
#     no more ins are present, the loop finishes."""
#     if finished is not None:
#         copy_to[finished]= None
# 
#     # NOTE:
#     # os.sendfile (self.dst, self.src, None, 0)
#     # OSError: [Errno 22] Invalid argument
#     # and splice() is not available
#     # so, copy by hand
#     selector = DefaultSelector ()
#     for src in copy_to.keys ():
#         if (     not isinstance (src, int)
#                 and (   getattr (src, 'fileno', None) is None
#                     or not isinstance (src.fileno(), int)) ):
#             logger.debug ('type mismatch: %s', src)
#         else:
#             logger.debug ("registering %s for read", src)
#             # if finished is also one of the srcs, then register() complains
#             try:
#                 selector.register (src, EVENT_READ)
#             except KeyError:
#                 pass
# 
#     def close_file (f):
#         if f in copy_to:
#             del copy_to[f]
# 
#         try:
#             selector.unregister (i)
#         except KeyError:
#             pass
# 
#         close (f)
# 
#     while len (copy_to)>0:
#         logger.debug (copy_to)
# 
#         events= selector.select ()
#         for key, _ in events:
#             logger.debug ("%s is ready to read", key)
#             i= key.fileobj
# 
#             # for error in e:
#             #     logger.debug ('%s error')
#                 # TODO: what?
# 
#             o= copy_to[i]
# 
#             try:
#                 data= read (i, buf_len)
#                 logger.debug2 ('%s -> %s: %s', i, o, data)
# 
#             # ValueError: read of closed file
#             except (OSError, ValueError) as e:
#                 logger.debug ('stopping copying for %s', i)
#                 logger.debug (traceback.format_exc ())
#                 close_file (i)
#                 break
#             else:
#                 if len (data)==0:
#                     logger.debug ('stopping copying for %s, no more data', i)
#                     close_file (i)
# 
#                     if finished is not None and i==finished:
#                         logger.debug ('finishing')
#                         # quite a hack :)
#                         copy_to= {}
# 
#                         break
#                 else:
#                     write (o, data)
# 
#     selector.close ()
#     logger.debug ('over and out')
# 
# def close (f):
#     logger.debug ('closing %s', f, callers=1)
#     try:
#         if isinstance (f, int):
#             os.close (f)
#         else:
#             if f is not None:
#                 f.close ()
#     except OSError as e:
#         logger.debug ('closing gave %s', e)
#         if e.errno!=errno.EBADF:
#             raise


import ayrton
import paramiko
import pickle
import types
import sys
import errno
import ctypes
import os
import traceback
import io
import shutil
import itertools
import paramiko.ssh_exception
import logging
from socket import socket, SO_REUSEADDR, SOL_SOCKET
from threading import Thread
from termios import tcgetattr, tcsetattr, TCSADRAIN
from termios import IGNPAR, ISTRIP, INLCR, IGNCR, ICRNL, IXON, IXANY, IXOFF
from termios import ISIG, ICANON, ECHO, ECHOE, ECHOK, ECHONL, IEXTEN, OPOST, VMIN, VTIME
from ayrton.utils import copy_loop, close
            logger.debug ('sending ast, globals, locals')
            # TODO: compress?
            self.result_channel.sendall (self.ast)
            self.result_channel.sendall (global_env)
            self.result_channel.sendall (local_env)

            # TODO: handle _in, _out, _err
            self.remote= RemoteStub (( (os.dup (0), i), (o, os.dup (1)), (e, os.dup (2)) ))
        except (paramiko.ssh_exception.SSHException, ConnectionError, OSError) as e:
            # NOTE: this is the only time we do this
            # please make sure the list of fileobjs is correct
            for fileobj in (self.result_channel, self.result_listen, self.client):
                close (fileobj)

            raise e


    def __exit__ (self, *args):
        logger.debug (args)
        data= b''
        partial= self.result_channel.recv (8196)
        while len(partial)>0:
            data+= partial
            partial= self.result_channel.recv (8196)

        logger.debug ('recieved %d bytes', len (data))
        (l, result, e)= pickle.loads (data)
        logger.debug ('result from remote: %r', result)
        logger.debug3 ('locals returned from remote: %s', ayrton.utils.dump_dict (l))
        logger.debug ('closing result_channel %s', self.result_channel)

# Path: ayrton/utils.py
# def copy_loop (copy_to, finished=None, buf_len=10240):
#     """copy_to is a dict(in: out). When any in is ready to read, data is read
#     from it and writen in its out. When any in is closed, it's removed from
#     copy_to. finished is a pipe; when data comes from the read end, or when
#     no more ins are present, the loop finishes."""
#     if finished is not None:
#         copy_to[finished]= None
# 
#     # NOTE:
#     # os.sendfile (self.dst, self.src, None, 0)
#     # OSError: [Errno 22] Invalid argument
#     # and splice() is not available
#     # so, copy by hand
#     selector = DefaultSelector ()
#     for src in copy_to.keys ():
#         if (     not isinstance (src, int)
#                 and (   getattr (src, 'fileno', None) is None
#                     or not isinstance (src.fileno(), int)) ):
#             logger.debug ('type mismatch: %s', src)
#         else:
#             logger.debug ("registering %s for read", src)
#             # if finished is also one of the srcs, then register() complains
#             try:
#                 selector.register (src, EVENT_READ)
#             except KeyError:
#                 pass
# 
#     def close_file (f):
#         if f in copy_to:
#             del copy_to[f]
# 
#         try:
#             selector.unregister (i)
#         except KeyError:
#             pass
# 
#         close (f)
# 
#     while len (copy_to)>0:
#         logger.debug (copy_to)
# 
#         events= selector.select ()
#         for key, _ in events:
#             logger.debug ("%s is ready to read", key)
#             i= key.fileobj
# 
#             # for error in e:
#             #     logger.debug ('%s error')
#                 # TODO: what?
# 
#             o= copy_to[i]
# 
#             try:
#                 data= read (i, buf_len)
#                 logger.debug2 ('%s -> %s: %s', i, o, data)
# 
#             # ValueError: read of closed file
#             except (OSError, ValueError) as e:
#                 logger.debug ('stopping copying for %s', i)
#                 logger.debug (traceback.format_exc ())
#                 close_file (i)
#                 break
#             else:
#                 if len (data)==0:
#                     logger.debug ('stopping copying for %s, no more data', i)
#                     close_file (i)
# 
#                     if finished is not None and i==finished:
#                         logger.debug ('finishing')
#                         # quite a hack :)
#                         copy_to= {}
# 
#                         break
#                 else:
#                     write (o, data)
# 
#     selector.close ()
#     logger.debug ('over and out')
# 
# def close (f):
#     logger.debug ('closing %s', f, callers=1)
#     try:
#         if isinstance (f, int):
#             os.close (f)
#         else:
#             if f is not None:
#                 f.close ()
#     except OSError as e:
#         logger.debug ('closing gave %s', e)
#         if e.errno!=errno.EBADF:
#             raise


# Path: ayrton/remote.py
import ayrton
import paramiko
import pickle
import types
import sys
import errno
import ctypes
import os
import traceback
import io
import shutil
import itertools
import paramiko.ssh_exception
import logging
from socket import socket, SO_REUSEADDR, SOL_SOCKET
from threading import Thread
from termios import tcgetattr, tcsetattr, TCSADRAIN
from termios import IGNPAR, ISTRIP, INLCR, IGNCR, ICRNL, IXON, IXANY, IXOFF
from termios import ISIG, ICANON, ECHO, ECHOE, ECHOK, ECHONL, IEXTEN, OPOST, VMIN, VTIME
from ayrton.utils import copy_loop, close

            logger.debug ('sending ast, globals, locals')
            # TODO: compress?
            self.result_channel.sendall (self.ast)
            self.result_channel.sendall (global_env)
            self.result_channel.sendall (local_env)

            # TODO: handle _in, _out, _err
            self.remote= RemoteStub (( (os.dup (0), i), (o, os.dup (1)), (e, os.dup (2)) ))
        except (paramiko.ssh_exception.SSHException, ConnectionError, OSError) as e:
            # NOTE: this is the only time we do this
            # please make sure the list of fileobjs is correct
            for fileobj in (self.result_channel, self.result_listen, self.client):
                close (fileobj)

            raise e


    def __exit__ (self, *args):
        logger.debug (args)
        data= b''
        partial= self.result_channel.recv (8196)
        while len(partial)>0:
            data+= partial
            partial= self.result_channel.recv (8196)

        logger.debug ('recieved %d bytes', len (data))
        (l, result, e)= pickle.loads (data)
        logger.debug ('result from remote: %r', result)
        logger.debug3 ('locals returned from remote: %s', ayrton.utils.dump_dict (l))
        logger.debug ('closing result_channel %s', self.result_channel)

        close(self.result_channel)