# Path: stoqdrivers/exceptions.py
# class InvalidReply(DriverError):
#     "Invalid reply received"
# 
# Path: stoqdrivers/interfaces.py
# class IScale(IDevice):
#     """ This interface describes how to interacts with scales.
#     """
# 
#     def read_data():
#         """ Read informations of the scale, returning an object
#         that implements IScaleInfo interface.
#         """
# 
# class IScaleInfo(Interface):
#     """ This interface list the data read by the scale """
#     weight = Attribute("The weight read")
#     price_per_kg = Attribute("The KG read")
#     total_price = Attribute("The total price. It is equivalent to "
#                             "price_per_kg * weight")
#     code = Attribute("The product code")
# 
# Path: stoqdrivers/serialbase.py
# class SerialBase(object):
# 
#     # All commands will have this prefixed
#     CMD_PREFIX = '\x1b'
#     CMD_SUFFIX = ''
# 
#     # used by readline()
#     EOL_DELIMIT = '\r'
# 
#     # Most serial printers allow connecting a cash drawer to them. You can then
#     # open the drawer, and also check its status. Some models, for instance,
#     # the Radiant drawers, use inverted logic to describe whether they are
#     # open, specified by this attribute, settable via BaseDevice config.
#     inverted_drawer = False
# 
#     def __init__(self, port):
#         self.set_port(port)
# 
#     def set_port(self, port):
#         self._port = port
# 
#     def get_port(self):
#         return self._port
# 
#     def fileno(self):
#         return self._port.fileno()
# 
#     def writeline(self, data):
#         self.write(self.CMD_PREFIX + data + self.CMD_SUFFIX)
#         return self.readline()
# 
#     def write(self, data):
#         # pyserial is expecting bytes but we work with str in stoqdrivers
#         data = str2bytes(data)
#         log.debug(">>> %r (%d bytes)" % (data, len(data)))
#         self._port.write(data)
# 
#     def read(self, n_bytes):
#         # stoqdrivers is expecting str but pyserial will reply with bytes
#         data = self._port.read(n_bytes)
#         return bytes2str(data)
# 
#     def readline(self):
#         out = ''
#         a = 0
#         retries = 10
#         while True:
#             if a > retries:
#                 raise DriverError(_("Timeout communicating with fiscal "
#                                     "printer"))
# 
#             c = self.read(1)
#             if not c:
#                 a += 1
#                 print('take %s' % a)
#                 continue
#             a = 0
#             if c == self.EOL_DELIMIT:
#                 log.debug('<<< %r' % out)
#                 return out
#             out += c
# 
#     def open(self):
#         if not self._port.is_open:
#             self._port.open()
# 
#     def close(self):
#         if self._port.is_open:
#             # Flush whaterver is pending to write, since port.close() will close it
#             # *imediatally*, losing what was pending to write.
#             self._port.flush()
#             self._port.close()
# 
# class SerialPort(Serial):
# 
#     def __init__(self, device, baudrate=9600):
#         # WARNING: Never change these default options, some drivers are based
#         # on this to work. Maybe we should change this and make all the driver
#         # specify its options, but right now I think that's ok, since these
#         # options are common to most of the drivers.
#         Serial.__init__(self, device, baudrate=baudrate, bytesize=EIGHTBITS,
#                         parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=3,
#                         write_timeout=3)
#         self.setDTR(True)
#         self.flushInput()
#         self.flushOutput()


from zope.interface import implementer
from stoqdrivers.exceptions import InvalidReply
from stoqdrivers.interfaces import IScale, IScaleInfo
from stoqdrivers.serialbase import SerialBase, SerialPort
        self.code = int(data[1:7])
        self.price_per_kg = float(data[12:18]) / (10 ** PRICE_PRECISION)
        self.weight = float(data[7:12]) / (10 ** QUANTITY_PRECISION)
        self.total_price = float(data[18:24]) / (10 ** PRICE_PRECISION)


@implementer(IScaleInfo)
class PackagePrt1:
    """ This class implements a parser for the protocol prt1 of Toledo Prix III

    this protocol does not require any interaction from the user. The driver
    queries the scale for the weight, and the scale replies
    """
    SIZE = 7

    def __init__(self, raw_data):
        self.code = None
        self.price_per_kg = None
        self.total_price = None
        self.weight = None
        self._parse(raw_data)

    def _parse(self, data):
        if not data:
            return
        elif ord(data[0]) != STX or len(data) != self.SIZE:
            raise InvalidReply("Received inconsistent data")
        self.weight = float(data[1:6]) / (10 ** QUANTITY_PRECISION)



# Path: stoqdrivers/exceptions.py
# class InvalidReply(DriverError):
#     "Invalid reply received"
# 
# Path: stoqdrivers/interfaces.py
# class IScale(IDevice):
#     """ This interface describes how to interacts with scales.
#     """
# 
#     def read_data():
#         """ Read informations of the scale, returning an object
#         that implements IScaleInfo interface.
#         """
# 
# class IScaleInfo(Interface):
#     """ This interface list the data read by the scale """
#     weight = Attribute("The weight read")
#     price_per_kg = Attribute("The KG read")
#     total_price = Attribute("The total price. It is equivalent to "
#                             "price_per_kg * weight")
#     code = Attribute("The product code")
# 
# Path: stoqdrivers/serialbase.py
# class SerialBase(object):
# 
#     # All commands will have this prefixed
#     CMD_PREFIX = '\x1b'
#     CMD_SUFFIX = ''
# 
#     # used by readline()
#     EOL_DELIMIT = '\r'
# 
#     # Most serial printers allow connecting a cash drawer to them. You can then
#     # open the drawer, and also check its status. Some models, for instance,
#     # the Radiant drawers, use inverted logic to describe whether they are
#     # open, specified by this attribute, settable via BaseDevice config.
#     inverted_drawer = False
# 
#     def __init__(self, port):
#         self.set_port(port)
# 
#     def set_port(self, port):
#         self._port = port
# 
#     def get_port(self):
#         return self._port
# 
#     def fileno(self):
#         return self._port.fileno()
# 
#     def writeline(self, data):
#         self.write(self.CMD_PREFIX + data + self.CMD_SUFFIX)
#         return self.readline()
# 
#     def write(self, data):
#         # pyserial is expecting bytes but we work with str in stoqdrivers
#         data = str2bytes(data)
#         log.debug(">>> %r (%d bytes)" % (data, len(data)))
#         self._port.write(data)
# 
#     def read(self, n_bytes):
#         # stoqdrivers is expecting str but pyserial will reply with bytes
#         data = self._port.read(n_bytes)
#         return bytes2str(data)
# 
#     def readline(self):
#         out = ''
#         a = 0
#         retries = 10
#         while True:
#             if a > retries:
#                 raise DriverError(_("Timeout communicating with fiscal "
#                                     "printer"))
# 
#             c = self.read(1)
#             if not c:
#                 a += 1
#                 print('take %s' % a)
#                 continue
#             a = 0
#             if c == self.EOL_DELIMIT:
#                 log.debug('<<< %r' % out)
#                 return out
#             out += c
# 
#     def open(self):
#         if not self._port.is_open:
#             self._port.open()
# 
#     def close(self):
#         if self._port.is_open:
#             # Flush whaterver is pending to write, since port.close() will close it
#             # *imediatally*, losing what was pending to write.
#             self._port.flush()
#             self._port.close()
# 
# class SerialPort(Serial):
# 
#     def __init__(self, device, baudrate=9600):
#         # WARNING: Never change these default options, some drivers are based
#         # on this to work. Maybe we should change this and make all the driver
#         # specify its options, but right now I think that's ok, since these
#         # options are common to most of the drivers.
#         Serial.__init__(self, device, baudrate=baudrate, bytesize=EIGHTBITS,
#                         parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=3,
#                         write_timeout=3)
#         self.setDTR(True)
#         self.flushInput()
#         self.flushOutput()


# Path: stoqdrivers/scales/toledo/PrixIII.py
from zope.interface import implementer
from stoqdrivers.exceptions import InvalidReply
from stoqdrivers.interfaces import IScale, IScaleInfo
from stoqdrivers.serialbase import SerialBase, SerialPort

        self.code = int(data[1:7])
        self.price_per_kg = float(data[12:18]) / (10 ** PRICE_PRECISION)
        self.weight = float(data[7:12]) / (10 ** QUANTITY_PRECISION)
        self.total_price = float(data[18:24]) / (10 ** PRICE_PRECISION)


@implementer(IScaleInfo)
class PackagePrt1:
    """ This class implements a parser for the protocol prt1 of Toledo Prix III

    this protocol does not require any interaction from the user. The driver
    queries the scale for the weight, and the scale replies
    """
    SIZE = 7

    def __init__(self, raw_data):
        self.code = None
        self.price_per_kg = None
        self.total_price = None
        self.weight = None
        self._parse(raw_data)

    def _parse(self, data):
        if not data:
            return
        elif ord(data[0]) != STX or len(data) != self.SIZE:
            raise InvalidReply("Received inconsistent data")
        self.weight = float(data[1:6]) / (10 ** QUANTITY_PRECISION)



@implementer(IScale)