# Path: picraft/exc.py
# class CommandError(ConnectionError):
#     "Exception raised when a network command fails"
# 
# class NoResponse(ConnectionError):
#     "Exception raised when a network command expects a response but gets none"
# 
# class BatchStarted(ConnectionError):
#     "Exception raised when a batch is started before a prior one is complete"
# 
# class BatchNotStarted(ConnectionError):
#     "Exception raised when a batch is terminated when none has been started"
# 
# class ConnectionClosed(ConnectionError):
#     "Exception raised when an operation is attempted against a closed connection"


import socket
import logging
import select
import threading
from .exc import (
        CommandError,
        NoResponse,
        BatchStarted,
        BatchNotStarted,
        ConnectionClosed,
        )

    def _send(self, buf):
        """
        Write *buf* (suitably encoded) to the socket.
        """
        if not self._socket:
            raise ConnectionClosed('connection closed')
        if not buf.endswith('\n'):
            buf += '\n'
        buf = buf.encode(self.encoding)
        if self.ignore_errors:
            self._drain()
        self._wfile.write(buf)
        logger.debug('>: %r', buf)

    def _receive(self, required=False):
        """
        Read a line from the socket, and return it (after decoding and
        stripping any trailing newline). If no response is received before
        :attr:`timeout` has elapsed, then the result depends on *required* and
        :attr:`ignore_errors`.  If *required* is ``False`` or
        :attr:`ignore_errors` is ``True``, the method simply returns ``None``.
        Otherwise, a :exc:`~picraft.exc.NoResponse` error is raised.

        If the response received is "Fail", a :exc:`~picraft.exc.CommandError`
        exception is raised (this is case even if :attr:`ignore_errors` is
        ``True`` to maintain compatibility with the reference implementation).
        """
        if not self._readable(self.timeout):
            if required and not self.ignore_errors:

# Path: picraft/exc.py
# class CommandError(ConnectionError):
#     "Exception raised when a network command fails"
# 
# class NoResponse(ConnectionError):
#     "Exception raised when a network command expects a response but gets none"
# 
# class BatchStarted(ConnectionError):
#     "Exception raised when a batch is started before a prior one is complete"
# 
# class BatchNotStarted(ConnectionError):
#     "Exception raised when a batch is terminated when none has been started"
# 
# class ConnectionClosed(ConnectionError):
#     "Exception raised when an operation is attempted against a closed connection"


# Path: picraft/connection.py
import socket
import logging
import select
import threading
from .exc import (
        CommandError,
        NoResponse,
        BatchStarted,
        BatchNotStarted,
        ConnectionClosed,
        )


    def _send(self, buf):
        """
        Write *buf* (suitably encoded) to the socket.
        """
        if not self._socket:
            raise ConnectionClosed('connection closed')
        if not buf.endswith('\n'):
            buf += '\n'
        buf = buf.encode(self.encoding)
        if self.ignore_errors:
            self._drain()
        self._wfile.write(buf)
        logger.debug('>: %r', buf)

    def _receive(self, required=False):
        """
        Read a line from the socket, and return it (after decoding and
        stripping any trailing newline). If no response is received before
        :attr:`timeout` has elapsed, then the result depends on *required* and
        :attr:`ignore_errors`.  If *required* is ``False`` or
        :attr:`ignore_errors` is ``True``, the method simply returns ``None``.
        Otherwise, a :exc:`~picraft.exc.NoResponse` error is raised.

        If the response received is "Fail", a :exc:`~picraft.exc.CommandError`
        exception is raised (this is case even if :attr:`ignore_errors` is
        ``True`` to maintain compatibility with the reference implementation).
        """
        if not self._readable(self.timeout):
            if required and not self.ignore_errors:

                raise NoResponse('no response received')